wait和notify是object类提供的线程协作机制,必须在synchronized块中调用;wait释放锁并进入等待队列,被notify/notifyall唤醒后需重新竞争锁;推荐用while循环检查条件并优先使用notifyall。

wait 和 notify 是 Object 类提供的底层线程协作机制,必须在 synchronized 代码块或方法中调用,否则会抛出 IllegalMonitorStateException。它们不用于控制执行顺序,而是用于线程间“条件等待”与“条件满足通知”。
wait() 的核心行为
调用 wait() 会让当前线程释放对象锁,并进入该对象的等待队列(WAITING 状态),直到被其他线程调用 notify() 或 notifyAll() 唤醒,或被中断、超时(如果用了带参版本)。
- 必须在已获取该对象锁的前提下调用(即在 synchronized 块内)
- 释放锁是自动的;被唤醒后需重新竞争锁,获得锁后才从
wait()返回 - 推荐始终用
while循环检查条件,避免虚假唤醒(spurious wakeup)
notify() 与 notifyAll() 的区别
notify() 随机唤醒一个在该对象上等待的线程;notifyAll() 唤醒所有等待线程。实际开发中优先使用 notifyAll(),除非你明确知道只有一个线程在等且唤醒逻辑绝对安全。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
-
notify()可能唤醒错的线程(比如条件不满足),导致死锁或逻辑错误 -
notifyAll()虽有开销,但语义更清晰、更健壮 - 两者都只唤醒,不释放锁;被唤醒线程仍需重新抢锁才能继续执行
典型使用模式:生产者-消费者场景
以共享缓冲区为例,用 wait/notifyAll 协调生产和消费:
synchronized (buffer) {
while (buffer.isEmpty()) {
buffer.wait(); // 消费者等待非空
}
int item = buffer.remove();
}
// …
synchronized (buffer) {
while (buffer.isFull()) {
buffer.wait(); // 生产者等待非满
}
buffer.add(item);
buffer.notifyAll(); // 通知所有等待方:状态可能变了
}
- 用
while而非if:防止唤醒后条件已失效(如多个消费者被唤醒,只有第一个能取走元素) - 每次修改共享状态后调用
notifyAll():让所有等待线程重新判断自身条件 - 锁对象必须是同一实例(如这里的
buffer),否则无法正确通信
常见陷阱与注意事项
这些细节容易引发死锁、无响应或异常:
- 在
wait()前没加同步 —— 运行时报IllegalMonitorStateException - 用
if判断条件 —— 可能跳过检查,导致取空或写满异常 - 用错锁对象(比如对
this同步,却对queue调用wait)—— 等待和通知不在同一个监视器上,完全无效 - 在循环中调用
wait()但未处理InterruptedException—— 中断信号被吞掉,线程无法响应中断
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










