wait()不能与lock结合使用,只能在synchronized中调用,依赖对象内置监视器锁;其本质是原子性释放锁并进入等待队列,唤醒后需重新竞争锁;lock体系应使用condition.await()/signal()替代;所谓“锁降级”在wait场景中属误用概念。

Java 中 wait() 方法本身**不能直接与 Lock(如 ReentrantLock)结合使用**,这是关键前提。它只能在 synchronized 块/方法中调用,且必须作用于被同步的对象——因为 wait() 依赖的是对象的**内置监视器锁(intrinsic lock)**,而 Lock 接口是显式、可编程的锁机制,二者底层互不兼容。
wait() 的锁行为本质:释放 + 重入
wait() 不是“降级”,而是**原子性释放当前持有的监视器锁,并使线程进入该对象的等待队列(_waitSet)**。当被 notify() 或 notifyAll() 唤醒后,线程不会立即执行,而是重新竞争该对象的监视器锁;只有成功获取锁后,才从 wait() 返回并继续执行。
- 调用
wait()前,线程必须已通过synchronized持有该对象锁 - 调用瞬间,锁被完全释放,其他线程可进入
synchronized块修改共享状态 - 唤醒后需再次抢锁,因此必须配合
while循环检查条件(防止虚假唤醒)
Lock 体系中对应 wait/notify 的正确方式:Condition
若你使用 ReentrantLock 等显式锁,应放弃 wait()/notify(),改用其配套的 Condition:
-
lock.newCondition()创建与该锁绑定的条件变量 -
condition.await()—— 功能等价于wait():释放锁 + 进入等待 -
condition.signal()/condition.signalAll()—— 等价于notify()/notifyAll() - 所有操作都发生在同一把
Lock上,无类型或语义冲突
所谓“锁降级”在 wait 场景中其实是误用概念
Java 官方文档和 HotSpot 实现中**不存在“wait 导致锁降级”这一机制**。“锁降级”通常指:
- 从写锁(如
ReentrantReadWriteLock.WriteLock)降为读锁(非阻塞获取) - 或在 synchronized 内部人为切换同步粒度(如先锁大对象再锁小对象),但这不是 JVM 提供的特性
-
wait()只是释放锁,不涉及“级别”变化;它释放的是唯一的监视器锁,没有“高阶/低阶”之分
实际协作建议:避免混用,按场景选型
不要试图把 wait() 塞进 Lock.lock() 块里——这会抛 IllegalMonitorStateException。正确做法是:
- 坚持使用
synchronized + wait/notify:适合简单、轻量的线程协作,代码简洁,JVM 优化成熟 - 需要高级控制(超时等待、多条件、可中断、公平策略)时,统一用
Lock + Condition - 若已有部分逻辑用
Lock,新增等待逻辑也必须走Condition.await(),保持一致性
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











