如何锁定一系列方法,以便其他线程调用那些相同的方法应该等待?

How to lock a sequence of methods, such that other thread call those same method should be waiting?

假设有一个线程,它有一系列的方法要执行:

public void task(){
   method();
   method();
   method();
   method();
}

我想锁定整个序列。也就是说,当 task() 正在执行时,我不希望其他线程执行相同的 method() 而是等到整个 task() 完成。需要什么样的锁?

您需要某种共享锁,并将其引用传递给需要执行该序列的所有线程。

例如,在 class 上创建一个 public static final ReentrantLock LOCK = new ReentrantLock();,其中包含 task() 方法,并在方法 task() 的开头写入 LOCK.lock();LOCK.unlock(); 在末尾。现在,所有通过 task() 方法的线程都将尝试获取锁,如果已经被占用,它将阻塞它们。

您可以使该任务 同步:

public synchronized void task() {
    method();
    method();
    method();
    method();
}

这将防止其他线程在同一对象上调用相同的 task() 方法,包括该对象上的其他 synchronized 方法。您可以使用显式 synchronized 语句进行更多控制,例如

public void task() {
    synchronized (this) { // or another object
        method();
        method();
        method();
        method();
    }
}

或使用您自己的 Lock 实例:

private final ReentrantLock lock = new ReentrantLock();
public void task() {
    lock.lock();  // block until lock is released
    try {
        method();
        method();
        method();
        method();
    } finally {
        lock.unlock();
    }
}

如果您想让所有 method() 调用都不是 运行 同时,只需将相同的机制应用于 method() 声明:

public synchronized void method() // or one of the other two options

如果将这三种机制中的一种应用于 taskmethod,您将确保调用 task() 的线程将完成所有 method() 调用顺序并防止其他线程同时调用任何 method()synchronizedReentrantLock 都允许同一个线程多次获得相同的 lock/monitor(嵌套锁)。

最后,如果你想允许对 method() 的多个并行调用,但只是在执行 task() 时不允许,你需要一个共享锁或 read-write 锁(参见 ReentrantReadWriteLock).

这可能是一个选项,但可能不是最好的。您可以这样修改 method() 的签名:

public void method(int serialExecutionCount) {
    synchronized(this) {
        for (int i = 0; i < serialExecutionCount; i++) {
            // body of your method()
        }
    }
}

现在,您的 task() 方法将如下所示:

public void task() {
   method(4);
}

现在,如果您像这样从其他线程调用它:

method(1);

它将等待 task() 方法的调用线程完成前 4 个方法调用。