我正在阅读使用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,则其中只有一个获得锁,另一个保持等待状态,因此在上述情况下,两个线程如何能够完成执行?
答案 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。