wait()释放的是当前线程在调用前通过synchronized获取的该对象的监视器锁,仅此一个,不释放其他锁;必须在同步上下文中调用,否则抛illegalmonitorstateexception。

调用 wait() 方法时,当前线程会立即释放它持有的对象监视器(即 synchronized 锁),然后进入该对象的等待队列,暂停执行,直到被其他线程唤醒或超时。
wait 释放的是哪个锁?
释放的是当前线程在调用 wait() 前通过 synchronized 获取的那个对象锁。必须在同步上下文中调用,否则抛出 IllegalMonitorStateException。
- 只能在
synchronized(obj) { obj.wait(); }或synchronized实例方法中调用 - 释放的是
obj的监视器锁,不是当前线程持有的其他锁(如 ReentrantLock) - 释放后,其他线程才能进入该对象的 synchronized 代码块
wait 后线程状态和锁的重新获取
线程进入 WAITING 状态,不占用 CPU;被 notify() 或 notifyAll() 唤醒后,并不会立刻恢复执行,而是先竞争重新获取该对象的锁。
- 唤醒后线程进入“锁池”,需等持有锁的线程退出同步块后,才能重新获得锁
- 获得锁后才从
wait()返回,继续执行后续代码 - 所以
wait()总是写在 while 循环里,防止虚假唤醒
典型正确用法示例
以生产者-消费者为例,确保条件检查、等待、唤醒逻辑安全:
synchronized (lock) {
while (queue.isEmpty()) {
try {
lock.wait(); // 释放 lock 锁,线程挂起
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return;
}
}
// 被唤醒后重新获得 lock 锁,再消费
item = queue.poll();
}
- 必须用
while而非if:避免虚假唤醒或条件已变 - 唤醒操作也必须在
synchronized(lock)中调用notify()/notifyAll() -
wait()返回时,一定已重新持有锁,无需额外同步
注意:wait 不释放所有锁
一个线程可能持有多个锁,wait() 只释放调用它的那个对象锁,其他锁保持不变。
- 例如:synchronized(A) { synchronized(B) { B.wait(); } } → 只释放 B 的锁,A 的锁仍持有
- 但嵌套同步加 wait 容易死锁,应避免复杂锁嵌套
- 若需释放多个资源,应考虑使用
java.util.concurrent工具类替代
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











