我以为我会理解Java中的并发概念,但现在有一件事让我理解不了:
为什么我必须在同步块中包含对wait()和notify()方法的调用?
假设我有两个线程:线程A和线程B.此外,我还有一个对象,我将其用作锁。
现在在某个时间点,线程A在对象上调用wait()
并在之后被阻塞,直到某个其他线程在同一对象上调用notify()
。到目前为止,这是我的理解,这很好。但是现在我需要将这些调用封装在这个对象上同步的块中 - 事实上,如果我不这样做,我会得到一个IllegalMonitorStateException
。如果我添加这些块,它工作正常 - 但为什么??
我原以为,如果我使用这些同步块,那么线程A将永远锁定对象,因为wait()
方法继续运行而线程B无法执行{{1}因为它无法获取对象的锁定,因为它仍然由线程A拥有。
然而,正如我所说的,实际上它工作正常,线程B可以执行notify()
解锁线程A ...有人可以解释一下这里发生了什么?线程B如何获得锁?
答案 0 :(得分:2)
当您在同步块中呼叫wait
时,监视器锁定将自动释放,请参阅doc:
线程释放此监视器的所有权并等到另一个监视器 线程通知在此对象的监视器上等待的线程唤醒 通过调用notify方法或notifyAll方法。 然后线程等待,直到它可以重新获得监视器的所有权 并恢复执行。
在另一个线程调用notify
并退出其synchronized
块之后,等待线程将被唤醒并尝试获取监视器锁以继续。
Breifly:
当只有notify()时,wait()才有意义,所以就是这样 总是关于线程之间的通信,以及那些需求 同步工作正常。
查看this了解更多信息。
答案 1 :(得分:1)
<强> BOTTOMLINE 强>:
wait
方法的调用实际上使一个线程&#34;释放其锁定&#34;然后暂停。
调用wait
时,线程A释放锁并暂停执行。在将来某个时候,线程B将获取相同的锁并调用Object.notifyAll
,通知所有线程(包括线程A)在该锁上等待发生重要事件。或Object.notify
,通过等待该锁的线程通知随机线程(线程A,如果它是等待该对象的唯一线程),发生了重要的事情。
在第二个线程B释放锁定后(当它存在同步块时),第一个线程A重新获取锁定,并通过从wait
的调用返回来恢复。