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

Java中wait()、notify()、notifyAll()为何需由持有监视器的线程调用?

为什么调用wait()/notify()/notifyAll()必须持有对象监视器所有权?

这背后本质是为了避免竞态条件、保证线程协作逻辑的正确性,具体可以拆解成这几个原因:

  • 防止检查条件与等待操作的竞态
    调用wait()的前提通常是先检查某个条件(比如队列是否为空),如果没有synchronized保护,线程A刚检查完条件为真,还没调用wait(),线程B就可能修改了条件并调用notify()。等A再调用wait()时,它已经错过了通知,会一直阻塞下去,这就导致了逻辑错误。synchronized能把「检查条件+调用wait()」变成原子操作,中间不会被其他线程打断。

  • 保证wait/notify的锁交互逻辑合法
    wait()执行时会自动释放当前持有的监视器锁,让其他线程能获取锁并修改条件。但你不能释放一个不属于你的锁——这就像你没法把别人的门打开让别人进一样。同样,notify()/notifyAll()是用来唤醒等待该监视器锁的线程,如果你没持有这个锁,你根本没有权限操作这个锁对应的等待队列,强行调用只会打乱其他线程的协作逻辑。

  • 避免不可预测的线程混乱
    Java通过抛出IllegalMonitorStateException来强制这个约束,本质是防止线程随意操作不属于自己的对象监视器。比如一个线程随便调用某个对象的notify(),可能会唤醒正在等待该对象的无关线程,导致这些线程错误地认为条件满足,进而执行错误的逻辑,让整个程序进入不可控状态。

举个生产者消费者模型的错误与正确对比:

// 错误写法:无synchronized,存在竞态风险且会抛异常
if (queue.isEmpty()) {
    queue.wait(); // 运行时直接抛IllegalMonitorStateException
}

// 正确写法:用synchronized保证原子性
synchronized(queue) {
    // 用while循环是为了被唤醒后再次检查条件(防止虚假唤醒)
    while (queue.isEmpty()) {
        queue.wait();
    }
    Object item = queue.poll();
}

内容的提问来源于stack exchange,提问作者Hossam

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 22:30:49