notify本身不实现精准调度,仅随机唤醒一个等待线程,精准调度依赖程序员设计的条件逻辑、锁保护与协作协议;其核心是通知条件可能变化,唤醒线程需重新竞争锁才能继续执行。

notify 方法本身不实现精准调度,它只负责唤醒一个在指定对象上等待的线程,而具体唤醒哪一个由 JVM 线程调度器随机决定。所谓“精准调度”,实际依赖的是程序员对条件逻辑、锁保护和协作协议的设计,notify 只是其中一环。
notify 的核心行为不是“选谁执行”,而是“通知条件可能已变”
它不控制执行顺序,也不保证唤醒后立即执行。它的作用是打破 wait 的阻塞,让被唤醒线程重新参与锁竞争——是否能抢到锁、何时执行,仍由 synchronized 机制和操作系统调度决定。
- 调用 notify 前,必须持有该对象的锁(即在 synchronized 块/方法内)
- notify 不释放锁,只有退出 synchronized 块时才释放
- 被唤醒的线程需重新获取锁后,才能从 wait() 返回继续执行
- 没有“按顺序唤醒”或“指定唤醒”的能力,多个等待线程中仅一个被选中(无序)
要达成看似“精准”的调度,必须配合状态判断与循环等待
单靠 notify 无法确保线程按预期逻辑执行;真正起作用的是“wait + while 循环 + 共享状态变量”的组合模式。
- 永远用 while 而非 if 判断等待条件(防止虚假唤醒)
- 共享状态(如 boolean isReady、int count)必须用 volatile 或受同一锁保护
- notify 应在修改状态后、且仍在同步块内调用
- 示例:生产者设 dataReady = true; notify(); 消费者 while(!dataReady) wait();
notify 和 notifyAll 的选择影响调度“精度”
在多线程竞争同一条件时,notify 容易遗漏本该响应的线程,导致死锁或饥饿;notifyAll 更稳妥,尤其当多个线程等待不同子条件时。
- 用 notify:适用于“一对一”场景(如一个生产者配一个消费者),且能确保每次只有一个线程满足条件
- 用 notifyAll:适用于一对多、条件复杂或存在多个等待类型(如读/写等待)的场景
- 误用 notify 可能造成部分线程永远等不到通知——这不是 notify 的缺陷,而是设计未覆盖所有唤醒路径
真正提升调度可控性的替代方案
若需强顺序、可预测的协作,建议优先使用更高层的并发工具,它们内部封装了更可靠的等待/通知语义:
- Condition(搭配 ReentrantLock):支持多个等待队列,可精确 signal 特定条件分支
- CountDownLatch / CyclicBarrier:用于固定阶段同步,无需手动管理 wait/notify
- Semaphore / BlockingQueue:面向资源或数据流的协调,逻辑更清晰、不易出错
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











