notifyAll之后2个线程如何获取锁?

时间:2019-07-09 09:47:50

标签: java multithreading wait synchronized

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

我通过了以下答案:https://stackoverflow.com/a/36276832

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

":syncronized block have finished"

但是我已经读到,如果有2个线程正在等待锁,则notifyAll将唤醒每个线程,但只有1个线程将获得锁。

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

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

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

有人可以回答。如果不清楚,我可以进一步解释我的疑问。

简单的问题:如果2个线程正在等待相同的锁,而第3个线程执行notifyAll,则其中只有一个获得锁,另一个保持等待状态,因此在上述情况下,两个线程如何能够完成执行?

2 个答案:

答案 0 :(得分:1)

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

在特定情况下,锁对象的所有者是两个线程同步的对象的主线程。当我们在锁对象上调用notify()方法时,如果您看到该文档,则说“ 仅单线程”被唤醒。因此,您将明白为什么程序将挂起第二个线程的原因从未被“通知”唤醒。释放进入“等待”状态的锁定的第一个线程实际上是被唤醒的线程。

如果您看到“ notifyAll()”的文档,它会指出“唤醒正在此对象的监视器上等待的所有线程。线程通过调用其中一个wait方法在对象的监视器上等待”。强调“全部”意味着您已经获得锁并等待被“通知”的两个线程都被唤醒。

以下是将调用从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

答案 1 :(得分:1)

当两个线程调用wait时,随后的notifyAll会将它们都唤醒,并将其中一个置于RUNNABLE状态(notifyAll上同步获取的获胜者),另一个则变为BLOCKED状态(正在等待获取监视器)。这遵循wait&notifyAll的语义。

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

此属性很重要,因此您应该始终重新检查使您首先处于等待状态的相同条件,这称为missed-signal