在调用condition.await时是否释放了重入锁?

时间:2016-04-07 13:08:33

标签: 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();

上的阻止
done.await();

然后另一个线程2调用synchronizer.signalAll()以发信号通知线程1.我的问题是线程2如何能够通过调用

来获取锁定
lock.lock();

之前打电话

done.signallAll();

当线程1最初获取锁定时?

我在这里找到了同样的问题:

Waiting on a condition in a reentrant lock

答案是:

  

Lock和synchronized都暂时允许其他人获取锁定   等他们的时候要停止等待,线程必须重新获取   锁。

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

答案还说明了:

  

注意:它们不会完全释放它,如果您采用堆栈跟踪   可以有多个线程似乎一次持有锁,   但最多其中一个将运行(其余的将等待)

然而,Condition.await()的文档声明:

  

与此条件关联的锁定以原子方式释放

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

1 个答案:

答案 0 :(得分:1)

  1. 线程1(T1)将在#await()lock.lock()调用
  2. 获取锁定
  3. T1将在#await()done.await()中释放锁定。 T1将停放,直至发出信号或中断,或者"虚假的醒来" *
  4. T2将在#signallAll()lock.lock
  5. 获取锁定
  6. T2将发出信号唤醒#signallAll()done.signalAll
  7. T2将释放锁#signallAll()lock.unlock
  8. T1将在#await()done.await()
  9. 中醒来
  10. T1将获得锁#await()done.await()
  11. T1将释放锁#await()lock.unlock()
  12. T1可能是"虚假的醒来"在运行T2的任何时候。但这将在done.await调用中发生。除非相关的锁被解锁且其他释放条件不正确(线程必须发出信号或中断),否则控制将永远不会被调回到调用者代码。