condition 与 object.wait 的本质差异在于“怎么等、为谁等、被谁唤醒”:前者通过显式多队列实现按需唤醒,后者依赖单一隐式队列导致随机唤醒;condition 基于 locksupport 提供精细控制与清晰契约,object.wait 则受限于 jvm monitor 黑盒机制。

Condition 的挂起机制和 Object.wait 的本质差异,核心不在“能不能等”,而在于“怎么等、为谁等、被谁唤醒”——它反映的是 Java 并发模型从粗粒度同步走向细粒度协作的演进。
等待队列的组织方式不同
Object.wait 依赖对象监视器(monitor),每个对象只有一个隐式等待队列。所有调用 this.wait() 的线程,无论业务意图是什么(比如“等有货”还是“等有空位”),都挤在同一个队列里。唤醒时只能靠 notify() 随机挑一个,或 notifyAll() 全部唤醒再竞争,效率低且易引发虚假唤醒。
Condition 则把等待队列显式化、语义化。一个 ReentrantLock 可绑定多个 Condition 实例,每个 Condition 独立维护自己的等待队列。例如:
- notEmpty:消费者等待“队列非空”,只在此队列上 await
- notFull:生产者等待“队列未满”,只在此队列上 await
signal() 只唤醒对应 Condition 队列里的线程,互不干扰,真正实现按需唤醒。
底层挂起原语与控制粒度不同
Object.wait 底层基于 JVM 的 monitor 机制,是语言内置的黑盒操作,无法定制中断行为、超时精度或唤醒策略。
Condition.await 底层基于 LockSupport.park/unpark,属于 JSR-166 提供的用户态线程调度原语。这带来更精细的控制能力:
- 支持 awaitUntil(Deadline):按绝对时间点唤醒,而非相对时长
- 支持 awaitUninterruptibly():明确声明不响应中断,避免业务逻辑被意外打断
- 可结合公平锁、读写锁等任意 Lock 实现,挂起逻辑与锁策略解耦
使用契约与错误边界更清晰
Object.wait/notify 要求必须在 synchronized 块内调用,否则抛 IllegalMonitorStateException,但这个约束是隐式的、运行时才暴露。
Condition 的契约更严格也更明确:
- 必须先调用 lock.lock(),再调用 condition.await()
- await() 内部会自动释放 lock,并在被 signal 后重新竞争获取 lock
- signal() 必须在 lock 持有时调用,否则同样抛 IllegalMonitorStateException
- 推荐始终用 while 循环检查条件,防止虚假唤醒 —— 这不是可选项,是设计强制要求
适用场景决定选型
简单单条件、轻量级协作(如小工具类中的简单同步),Object.wait/notify 足够,代码更短。
一旦涉及:
- 多条件等待(生产者/消费者、读/写/删除等不同阻塞原因)
- 需要超时控制、绝对时间唤醒、中断屏蔽等高级语义
- 已使用 ReentrantLock 或其他 Lock 实现(比如带超时的 tryLock)
就必须用 Condition —— 它不是 wait 的替代品,而是为复杂协作场景专门设计的升级路径。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











