【问题标题】:Is a reentrant lock released when calling its condition.await?调用condition.await时是否释放了可重入锁?
【发布时间】:2016-04-07 13:08:33
【问题描述】:

我有以下代码:

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() 的文档指出:

与此条件关联的锁被原子释放

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

【问题讨论】:

    标签: java multithreading locking


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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-06-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-06-07
      • 1970-01-01
      相关资源
      最近更新 更多