java - 调用其condition.await时是否会释放可重入锁?

标签 java multithreading locking

我有以下代码:

public class Synchronizer {

    private final Lock lock = new ReentrantLock();
    private final Condition done = lock.newCondition();
    private boolean isDone = false;

    private void signalAll() {

        lock.lock(); // MUST lock!
        try {
            isDone = true; // To help the await method ascertain that it has not waken up 'spuriously'
            done.signalAll();
        }
        finally {
            lock.unlock(); // Make sure to unlock even in case of an exception
        }
    }

    public void await() {

        lock.lock(); // MUST lock!
        try {
            while (!isDone) { // Ascertain that this is not a 'spurious wake-up'
                done.await();
            }
        }
        finally {
            isDone = false; // for next time
            lock.unlock(); // Make sure to unlock even in case of an exception
        }
    }
}

假设线程1调用synchornizer.await()并通过获取锁

lock.lock();

和 block

done.await();

然后另一个线程2调用synchronizer.signalAll()来向线程1发出信号。我的问题是线程2如何能够通过调用来获取锁

lock.lock();

打电话之前

done.signallAll();

线程 1 最初何时获取锁?

我在这里发现了同样的问题:

Waiting on a condition in a reentrant lock

答案是:

Both Lock and synchronized temporarily allow others to obtain the lock when they are waiting. To stop waiting, a thread have to re-acquire the lock.

我试图理解这是否意味着如果线程1没有调用done.await(),线程2将无法获取锁?

答案还指出:

Note: They don't release it fully and if you take a stack trace you can have multiple threads which appear to be holding the lock at once, but at most one of them will be running (the rest will be waiting)

然而 Condition.await() 的文档指出:

The lock associated with this Condition is atomically released

那么锁是否被释放以及“他们没有完全释放它”是什么意思?

最佳答案

  1. 线程 1 (T1) 将在 #await() lock.lock() 调用时获取锁
  2. T1 将在#await() did.await() 处释放锁定。 T1 将 parking ,直到收到信号或中断或“虚假唤醒”*
  3. T2 将在 #signallAll() lock.lock 处获取锁
  4. T2 将发出唤醒信号#signallAll() did.signalAll
  5. T2 将释放锁#signallAll() lock.unlock
  6. T1 将在 #await() did.await() 处唤醒
  7. T1 将获取锁 #await() did.await()
  8. T1 将释放锁 #await() lock.unlock()

T1 可能在运行 T2 的任何时刻被“虚假唤醒”。但这将在done.await 调用内发生。控制权永远不会返回给调用者代码,除非关联的锁已解锁并且其他释放条件不正确(线程必须发出信号或中断)。

关于java - 调用其condition.await时是否会释放可重入锁?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36477197/

相关文章:

java - 同步方法是否在进入非同步块(synchronized block)时释放锁?

ruby - 在Thread ruby​​中杀死系统进程

java - 是否可以从流中打开 TrueZIP 存档?

java - 排序算法

C++ `Timer` 类实现

java - 如何等到 Java 中的另一个线程释放锁?

c# - 为什么要使用 Mutex 来锁定?

javascript - 从WebWorker同步获取数据?

java - 新手问题(Java): problem with simple battleship game

java - MediaRecorder 启动失败错误