Java 添加进程锁

引言

在多线程编程中,有时候需要确保多个线程不会同时访问特定的代码块或资源。为了避免数据竞争和不一致的状态,可以使用进程锁来进行同步。进程锁是一种并发控制机制,它确保在同一时间只有一个线程可以访问被锁定的代码块或资源。

Java 提供了多种实现进程锁的方法,比如使用 synchronized 关键字、ReentrantLock 类等。本文将介绍这些方法,并提供示例代码来说明如何使用它们。

使用 synchronized 关键字

synchronized 关键字是 Java 中最基本和简单的同步机制。它可以用于修饰方法或代码块,以确保同一时间只有一个线程可以执行被修饰的代码。

修饰方法

可以将 synchronized 关键字直接应用于方法上,将整个方法体作为临界区。下面是一个使用 synchronized 修饰方法的示例:

public class SynchronizedExample {

    private int counter = 0;

    public synchronized void increment() {
        counter++;
    }

    public synchronized void decrement() {
        counter--;
    }

    public int getCounter() {
        return counter;
    }
}

在上述代码中,incrementdecrement 方法都被用 synchronized 修饰,这意味着在同一时间只有一个线程可以执行这两个方法。这样就可以确保 counter 变量的增减操作是线程安全的。

修饰代码块

除了修饰方法,synchronized 还可以修饰代码块。通过将关键字应用于代码块,可以将更精确的部分作为临界区。

下面是一个使用 synchronized 修饰代码块的示例:

public class SynchronizedExample {

    private int counter = 0;

    public void increment() {
        synchronized (this) {
            counter++;
        }
    }

    public void decrement() {
        synchronized (this) {
            counter--;
        }
    }

    public int getCounter() {
        return counter;
    }
}

在上述代码中,incrementdecrement 方法中的 synchronized (this) 块表示只有一个线程可以同时进入这个块中的代码。这样同样可以确保 counter 变量的增减操作是线程安全的。

使用 ReentrantLock 类

ReentrantLock 类是 Java 提供的另一种实现进程锁的方法。与 synchronized 关键字相比,ReentrantLock 提供了更多的灵活性和功能。

下面是一个使用 ReentrantLock 的示例:

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class ReentrantLockExample {

    private int counter = 0;
    private Lock lock = new ReentrantLock();

    public void increment() {
        lock.lock();
        try {
            counter++;
        } finally {
            lock.unlock();
        }
    }

    public void decrement() {
        lock.lock();
        try {
            counter--;
        } finally {
            lock.unlock();
        }
    }

    public int getCounter() {
        return counter;
    }
}

在上述代码中,ReentrantLock 的实例是用 lock 方法进行加锁操作的,与之对应的是使用 unlock 方法进行解锁操作。这样可以确保同一时间只有一个线程可以进入临界区,从而实现线程安全。

进程锁的选择

在使用进程锁时,需要根据实际情况选择合适的方法。synchronized 是最简单和最常用的方法,但它的功能相对有限。而 ReentrantLock 则提供了更多的功能,比如可重入性、公平性等。

下表是 synchronizedReentrantLock 的一些比较:

特性 synchronized ReentrantLock
可重入性 支持 支持
公平性 不支持 支持
中断响应 不支持 支持