LeetCode 1114:notify()触发超时,notifyAll()正常的原因解析
为什么LeetCode 1114题中notify()会超时,而notifyAll()可以正常运行?
核心区别:notify()与notifyAll()的唤醒逻辑
notify():仅随机唤醒一个等待当前对象锁的线程,无法指定唤醒目标。notifyAll():唤醒所有等待当前对象锁的线程,让它们重新竞争锁并检查执行条件。
结合题目场景的具体分析
LeetCode 1114要求三个线程严格按first→second→third的顺序执行。实际测试中,线程的启动顺序不一定是first先运行,可能出现second和third先启动的情况:
- 此时
second会因oneDone=false进入wait(),third会因twoDone=false进入wait(),两个线程都在等待锁。 - 当
first执行完毕调用notify()时,只会随机唤醒其中一个线程:- 如果唤醒的是
second:second满足条件执行,完毕后调用notify()再唤醒third,流程正常。 - 如果唤醒的是
third:third醒来后检查twoDone仍为false,会再次进入wait()。此时second还在等待状态,没有被唤醒,整个程序陷入停滞,最终触发超时(TLE)。
- 如果唤醒的是
- 换成
notifyAll()后:first执行完调用notifyAll(),会同时唤醒second和third。third检查条件不满足会重新等待,而second满足条件正常执行。second执行完再调用notifyAll(),唤醒third,third检查条件满足后执行,整个流程不会卡住。
补充说明:while循环的作用
代码中用while而非if检查条件,是为了处理虚假唤醒(线程被唤醒但条件仍不满足的情况)。但notify()的问题不在于虚假唤醒,而在于唤醒的线程不符合执行条件,导致真正需要执行的线程一直处于等待状态。
你的实现代码
class Foo { private boolean oneDone; private boolean twoDone; public Foo() { oneDone = false; twoDone = false; } public synchronized void first(Runnable printFirst) throws InterruptedException { printFirst.run(); oneDone = true; //notify(); notifyAll(); } public synchronized void second(Runnable printSecond) throws InterruptedException { while (!oneDone) { wait(); } printSecond.run(); twoDone = true; //notify(); notifyAll(); } public synchronized void third(Runnable printThird) throws InterruptedException { while (!twoDone) { wait(); } printThird.run(); } }
内容的提问来源于stack exchange,提问作者xyz xyz
相关产品推荐
相关产品推荐

