wait()必须在synchronized块中调用,否则抛illegalmonitorstateexception;目的是确保条件判断与等待原子执行、锁能正确释放与重入,并与notify/notifyall协同工作。

因为 wait() 会释放当前线程持有的锁,而只有已经持有锁的线程才能合法释放它——Java 强制要求调用前必须已获得对象监视器(即进入 synchronized 块或方法),否则抛出 IllegalMonitorStateException。
防止竞态与状态不一致
调用 wait() 前通常要检查某个条件(比如缓冲区是否为空)。若不在同步块中,条件判断和 wait() 之间可能被其他线程修改状态,导致“条件满足却仍等待”或“错过唤醒”。同步块保证判断和等待原子执行。
确保锁的正确释放与重入
wait() 的语义是:释放锁 → 挂起线程 → 被唤醒后重新竞争并获取同一把锁 → 恢复执行。这个过程依赖 JVM 对监视器的严格管理。只有在 synchronized 中,JVM 才能准确追踪“谁持有了这把锁”,从而安全地释放和后续恢复。
与 notify/notifyAll 配套设计
notify() 和 wait() 共享同一套监视器机制。它们必须作用于同一个对象且都在其同步上下文中,才能保证唤醒动作真正作用于正在该对象上等待的线程。脱离同步块调用,唤醒可能无效或不可见。
实际写法示例
正确方式:
synchronized (obj) {
while (!condition) {
obj.wait(); // 安全:已持锁,可释放
}
// 条件满足,继续处理
}
错误方式(运行时报异常):
obj.wait(); // 抛 IllegalMonitorStateException
常见疏漏:
- 用
if判断条件而非while,导致虚假唤醒后跳过检查 - 同步对象和
wait()调用对象不一致(如 synchronized(lockA) 却 lockB.wait()) - 在 ReentrantLock 等显式锁中误用
wait()(应使用Condition.await())
本质不是语法限制,而是并发语义的强制契约:等待必须发生在对共享状态有排他控制的前提下。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











