synchronized 不能精准唤醒,因为 notify() 随机唤醒一个等待线程,不保证顺序、优先级或条件匹配,且不接收参数;精准唤醒需依赖 Lock + Condition。

Java 中 synchronized 本身不直接支持条件变量(如 pthread 的 condition variable),也无法实现“精准唤醒”——它只能通过 wait()/notify()/notifyAll() 配合手动状态检查来模拟,且 notify() 是**非确定性唤醒**,无法指定唤醒某个特定等待线程。
为什么 synchronized 不能精准唤醒?
notify() 只是随机唤醒一个在该对象监视器上等待的线程,JVM 不保证顺序、优先级或条件匹配;它不接收参数,也不区分“谁在等什么”。所谓“精准唤醒”,必须依赖更高层的逻辑控制,而非原语能力。
用 wait/notify 模拟条件变量的正确姿势
关键不是“精准唤醒”,而是“避免虚假唤醒 + 确保条件成立后再继续”。必须用 while 循环检查条件,而不是 if:
- 用共享变量(如 boolean flag、int status)表示业务条件
- 所有修改条件的地方(如 setReady(true))都要同步,并调用 notify()/notifyAll()
- 所有等待方必须在 synchronized 块内用 while 检查条件,不满足则 wait()
- 优先用
notifyAll():多个条件共用同一锁时,notify() 可能唤醒错的线程,导致死锁或饥饿
示例:生产者-消费者中只唤醒“有数据可取”的消费者
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
立即学习“Java免费学习笔记(深入)”;
synchronized (lock) {
while (queue.isEmpty()) {
lock.wait(); // 等待数据
}
int data = queue.poll();
}
// 生产者端:
synchronized (lock) {
queue.offer(item);
lock.notifyAll(); // 唤醒所有等待者,由它们各自判断条件
}
真正支持精准唤醒的替代方案:Lock + Condition
如果需要按不同条件独立唤醒(如“有数据”和“空间可用”分别管理),应使用 java.util.concurrent.locks.ReentrantLock 和 Condition:
- 一个 Lock 可创建多个 Condition 实例,每个代表一类等待条件
-
condition.signal()只唤醒等待该 Condition 的线程,天然隔离 - 仍需配合 while 循环检查条件,但唤醒目标明确
示例:
Lock lock = new ReentrantLock();
Condition notEmpty = lock.newCondition();
Condition notFull = lock.newCondition();
// 消费者等待非空
lock.lock();
try {
while (queue.isEmpty()) notEmpty.await();
return queue.poll();
} finally { lock.unlock(); }
// 生产者发信号
lock.lock();
try {
queue.offer(item);
notEmpty.signal(); // 精准唤醒等待“非空”的线程
} finally { lock.unlock(); }
小结:synchronized 的局限与出路
synchronized 是重量级但简洁的内置锁,适合简单互斥;它没有条件队列抽象,notify() 不可预测。若需多条件、可中断等待、超时等待或真正精准唤醒,必须转向 Lock 体系。不要强行用 synchronized + notify() 实现复杂条件协调——容易出错且不可维护。

















