notifyAll 后 2 线程如何获取锁?

How does 2 thread able to acquire lock after notifyAll?

我正在阅读 Java 中使用 wait/notify/notifyAll 的线程间通信。

我通过了这个答案:

有2个线程和1个主线程。主线程做notifyAll。它唤醒剩余的 2 个线程,并且两个线程都打印

":syncronized block have finished"

但是我读到如果有 2 个线程在等待锁,notifyAll 会唤醒每个线程,但锁只会被 1 个线程获取。

所以我的问题是 t1 和 t2 线程如何完成它们的执行?

当我从 lock.notifyAll(); 更改为 lock.notify(); 时,Java 程序永远不会结束。

t1/t2 中的一个线程将处于等待状态。

有人能回答一下吗?我的疑惑我可以再解释一下,以防没看明白。

简单来说就是问题:如果2个线程在等待同一个锁,第3个线程执行notifyAll,只有其中一个获得锁,另一个保持等待状态,那么在上面的例子中,为什么两个线程都能够完成执行呢?

您问题的答案隐藏在 notify() and notifyAll() 方法的文档中。

在您的特定情况下,两个线程同步的锁对象的所有者是主线程。当我们在锁对象上调用 notify() 方法时,如果您看到文档,它会说“only single thread”被唤醒。因此你明白为什么程序会挂起第二个线程永远不会 "notfied" 被唤醒。第一个在进入 "waiting" 状态时释放锁的线程实际上是被唤醒的线程。

如果你看到 "notifyAll()" 的文档,它指出 "Wakes up all threads that are waiting on this object's monitor. A thread waits on an object's monitor by calling one of the wait methods." 强调 "all" 意味着你的线程已经获得锁并等待 [=29= 】 被唤醒。

下面是我们将调用从 notifyAll() 更改为 notify() 时的结果,在这种情况下第一个执行等待的线程会得到通知。

Time: Tue Jul 09 12:42:37 CDT 2019;Thread-1:thread goes into waiting state and releases the lock
Time: Tue Jul 09 12:42:37 CDT 2019;Thread-0:only one thread can be in synchronized block
Time: Tue Jul 09 12:42:42 CDT 2019;Thread-0:thread goes into waiting state and releases the lock
Time: Tue Jul 09 12:42:47 CDT 2019;Notifying all
Time: Tue Jul 09 12:42:47 CDT 2019;Thread-1:thread is awake and have reacquired the lock
Time: Tue Jul 09 12:42:47 CDT 2019;Thread-1:syncronized block have finished

当两个线程调用 wait 时,随后的 notifyAll 将唤醒它们并将一个线程置于 RUNNABLE 状态(在 notifyAll 上同步获取的赢家),另一个进入 BLOCKED 状态(等待获取监视器)。这遵循 wait 和 notifyAll 的语义。

BLOCKED 线程的规则是在当前持有监视器的另一个 RUNNABLE 线程退出后获取监视器。这就是您看到两个输出的原因。

这个 属性 很重要,为什么你应该总是 re-check 让你首先等待的相同条件,这被称为 missed-signal