Java中调用notifyAll后,为何两个等待线程都能完成执行?
解答你的wait/notifyAll线程通信疑问
嘿,这个问题问到点子上了!很多刚接触Java线程通信的开发者都会在这里绕晕,我来给你掰扯清楚:
核心逻辑:notifyAll不是让线程“同时执行”,而是让它们“依次竞争锁”
你之前的理解没错——同一时间只有一个线程能拿到对象锁,但notifyAll的作用是把所有在该锁上等待的线程都唤醒,让它们进入锁的竞争队列,而不是只唤醒一个。
举个对应你场景的例子:
- 主线程调用
lock.notifyAll()后,t1和t2都从wait状态被唤醒,变成可运行状态,开始竞争lock对象的锁。 - 假设t1先抢到锁,进入同步块执行代码,输出你看到的
:synchronized block have finished,执行完后释放lock锁。 - 这时候t2就有机会抢到刚释放的锁,进入自己的同步块执行代码,同样输出那句话,执行完释放锁。
所以两个线程最终都能完成执行,只是有先后顺序而已。
为什么用notify()时程序会卡着?
notify()和notifyAll的区别就在这里:notify只会随机唤醒一个在该锁上等待的线程,另一个线程还留在等待队列里,没人去唤醒它。
比如你用notify()时,可能只唤醒了t1,t2还在wait状态;或者只唤醒了t2,t1还在等。这个没被唤醒的线程会一直处于等待状态,而JVM必须等所有非守护线程结束才会退出,所以你的程序就永远停着,不会结束。
再补个关键细节
被notify/notifyAll唤醒的线程,不是直接继续执行wait之后的代码,而是必须重新获取对象锁,只有拿到锁才能继续往下走。这就是为什么即使notifyAll唤醒了所有线程,它们也不会同时执行,而是排队抢锁依次执行。
内容的提问来源于stack exchange,提问作者Nicky
相关产品推荐
相关产品推荐

