notify方法必须在同步代码块或方法中调用,且当前线程必须持有该对象锁,否则抛IllegalMonitorStateException;它唤醒一个等待线程但不释放锁,被唤醒线程需重新竞争锁才能继续执行。

notify 方法必须在同步代码块或同步方法中调用,且当前线程必须持有该对象的锁,否则会抛出 IllegalMonitorStateException。 它的作用是唤醒一个正在该对象上等待(wait)的线程,但不会释放锁——锁仍由当前 notify 调用者持有,直到同步块结束或显式释放。
notify 前提:线程必须已获取对象锁
Java 中的 wait/notify 机制绑定在对象监视器(monitor)上。只有获得对象内置锁(即进入 synchronized 块或方法)后,才能合法调用其 notify() 或 wait()。例如:
// ✅ 正确:synchronized 确保当前线程持有 obj 锁
synchronized (obj) {
obj.notify(); // 可安全调用
}
// ❌ 抛异常:未持有锁就调用 notify
obj.notify(); // IllegalMonitorStateException
notify 不释放锁,仅唤醒等待线程
调用 notify() 本身不导致锁释放。被唤醒的线程不会立即执行,它需要重新竞争该对象的锁。只有当 notify 所在的同步块退出(或锁被其他方式释放),被唤醒线程才可能获得锁并从 wait() 返回。常见误区是认为 notify 后等待线程立刻运行——实际调度取决于 JVM 和线程状态。
- notify() 仅将一个等待线程从 wait set 移入 entry set(准备争锁)
- 原 notify 线程继续执行,直到退出 synchronized 块,才释放锁
- 被唤醒线程需再次获得锁后,才能从 wait() 返回并继续执行
配合条件变量使用的典型模式
notify 应与 while 循环检查条件配合,避免虚假唤醒和条件失效。锁、条件判断、wait/notify 必须使用同一把锁:
立即学习“Java免费学习笔记(深入)”;
synchronized (lock) {
if (!conditionMet) {
lock.wait(); // 释放锁并等待
}
}
// 其他线程修改条件后:
synchronized (lock) {
conditionMet = true;
lock.notify(); // 唤醒一个等待者
}
注意:用 if 可能漏唤醒,推荐用 while 重检条件;notifyAll 更适用于多条件或不确定等待者数量的场景。
notify 与 notifyAll 的选择要点
- notify 适合“单一生产者-单一消费者”或明确只需唤醒一个线程的场景
- notifyAll 更安全:避免因唤醒错线程导致死锁或逻辑卡住(比如多个等待线程关心不同条件)
- 即使只期望唤醒一个,若无法确保所有等待线程处理的是同一条件,应优先用 notifyAll


















