notify不释放锁,仅将一个等待线程从wait set移至lock queue,该线程需竞争锁成功后才能继续执行;必须在synchronized块中调用,否则抛出illegalmonitorstateexception。

notify 方法本身不参与锁竞争,它只负责“通知”,真正参与锁竞争的是被唤醒的线程。
notify 不释放锁,也不移交执行权
调用 notify() 的线程不会在调用那一刻释放对象锁。它会继续执行同步块中剩余代码,直到退出 synchronized 作用域(即大括号结束)后,才真正释放锁。此时,被 notify 唤醒的线程才进入锁池(Lock Queue),和其他等待获取该锁的线程(包括刚释放锁的线程、新尝试进入的线程等)一起公平竞争——这个过程由 JVM 锁竞争机制(如 CAS + 队列调度)决定,不是 notify 直接分配的。
被唤醒线程需重新抢锁才能继续
notify 只是把一个等待线程从等待队列(Wait Set)移到同步队列(Lock Queue),状态由 WAITING → BLOCKED。该线程并不会立即恢复运行,而是要:
- 等待当前持有锁的线程(可能是 notify 调用者,也可能是其他线程)完全释放锁;
- 在锁池中与其他线程竞争该对象监视器;
- 成功获取锁后,状态变为 RUNNABLE,才能从 wait() 调用处返回,继续执行后续逻辑。
notify 是随机唤醒,不保证顺序
如果有多个线程在同一个对象上 wait,notify() 仅唤醒其中**一个**,且选择是 JVM 内部决定的,不遵循 FIFO 或优先级——没有“先 wait 先 notify”的保障。这意味着:
- 若被唤醒的线程条件仍不满足(比如生产者唤醒了消费者,但缓冲区仍是空的),它可能再次 wait;
- 其他仍在等待的线程可能长期得不到机会,造成“饥饿”;
- 因此在条件不确定或存在多个等待方时,更推荐用 notifyAll()。
必须与 synchronized 配合使用
notify() 必须在持有同一对象锁的同步上下文中调用,否则抛出 IllegalMonitorStateException。这是因为:
- 只有持锁线程才有权限操作该对象的等待队列;
- 确保“通知”和“条件变更”发生在原子语义内(例如:修改共享变量后 notify,避免竞态);
- 防止唤醒发生在条件尚未稳定更新完成之前。
不复杂但容易忽略。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











