Condition是Java并发包中需与ReentrantLock配合使用的线程等待唤醒工具,支持多等待队列和精准唤醒,必须通过lock.newCondition()创建,await/signal需在加锁后调用并配合循环条件检查。

Condition 是 Java 并发包中用于实现线程间精确等待与唤醒的核心工具,它必须和 ReentrantLock 配合使用,不能单独创建。相比 Object 的 wait/notify,Condition 支持多个等待队列,能按业务逻辑分组唤醒,避免“虚假唤醒”或“全量唤醒”带来的性能浪费。
Condition 必须绑定 ReentrantLock 使用
Condition 实例由 Lock 对象通过 newCondition() 方法创建,每个 Condition 对应一个独立的等待队列。一个 Lock 可以创建多个 Condition,从而实现不同条件下的精准唤醒。
- 错误用法:直接 new Condition() —— 编译不通过,Condition 是接口,无 public 构造器
- 正确方式:
ReentrantLock lock = new ReentrantLock(); Condition condA = lock.newCondition(); - 多个 Condition 示例:生产者用
notFull,消费者用notEmpty,互不干扰
await() 和 signal() 的配对使用规则
调用 await() 前必须已持有锁,执行时会自动释放锁并进入等待队列;signal() 不释放锁,只将等待队列中的一个线程移入同步队列,由其在锁释放后竞争获取。
在调试 Java 后端 API 故障时使用此技能,尤其适用于以下任务:分析日志、跨 Controller、Service 和 Mapper 层追踪请求、定位异常根因、检查 SQL 执行或参数流转,以及生成简洁的诊断结论与修复方案。
- await() 必须在 lock.lock() 之后、lock.unlock() 之前调用,否则抛 IllegalMonitorStateException
- signal() / signalAll() 同样需在加锁后调用,否则无效且可能引发异常
- 推荐在 while 循环中 await,检查条件是否真正满足(防止虚假唤醒),例如:
while (!canProceed()) cond.await();
多 Condition 实现差异化唤醒
典型场景如阻塞队列:当队列满时,生产者 await(notFull);当队列空时,消费者 await(notEmpty)。添加元素后只 signal(notEmpty),移除元素后只 signal(notFull),避免唤醒无关线程。
立即学习“Java免费学习笔记(深入)”;
- 一个 Condition 对应一类等待逻辑,比如“库存不足”、“订单未就绪”、“网络未连通”
- signal() 唤醒单个等待线程,signalAll() 唤醒全部 —— 根据公平性与吞吐量权衡选择
- 注意:被 signal 的线程不会立即执行,仍需重新竞争锁,获得锁后从 await() 返回继续执行
异常处理与资源清理
await() 可能被中断(抛 InterruptedException),signal() 不抛异常但需确保锁状态安全。建议在 finally 块中 unlock,避免死锁。
- await() 被中断后,当前线程的中断状态会被清除,如需保留,需手动调用 Thread.currentThread().interrupt()
- 不要在 await() 后直接假设条件成立,始终用循环检查业务条件
- signal() 后无需立即 unlock,可继续执行其他操作,只要保证最终 unlock 即可

















