You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

LeetCode 1114:notify()触发超时,notifyAll()正常的原因解析

为什么LeetCode 1114题中notify()会超时,而notifyAll()可以正常运行?

核心区别:notify()与notifyAll()的唤醒逻辑

  • notify():仅随机唤醒一个等待当前对象锁的线程,无法指定唤醒目标。
  • notifyAll():唤醒所有等待当前对象锁的线程,让它们重新竞争锁并检查执行条件。

结合题目场景的具体分析

LeetCode 1114要求三个线程严格按first→second→third的顺序执行。实际测试中,线程的启动顺序不一定是first先运行,可能出现second和third先启动的情况:

  1. 此时second会因oneDone=false进入wait(),third会因twoDone=false进入wait(),两个线程都在等待锁。
  2. 当first执行完毕调用notify()时,只会随机唤醒其中一个线程:
    • 如果唤醒的是second:second满足条件执行,完毕后调用notify()再唤醒third,流程正常。
    • 如果唤醒的是third:third醒来后检查twoDone仍为false,会再次进入wait()。此时second还在等待状态,没有被唤醒,整个程序陷入停滞,最终触发超时(TLE)。
  3. 换成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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 17:27:15