虚假唤醒是线程未被显式通知却从wait()返回的合法现象,须用while循环重检条件、synchronized同步块和notifyAll()组合防御,确保条件满足才执行业务逻辑。
虚假唤醒是指线程在没有被显式调用 notify() 或 notifyAll() 的情况下,从 wait() 中意外返回的现象。它不是 bug,而是 JVM 和操作系统允许的合法行为,必须在代码层面主动防御。
底层调度机制无法完全保证“只唤醒该通知的目标线程”。比如:
某些中断、超时或系统资源抖动时提前恢复线程用 if 检查条件再 wait,一旦发生虚假唤醒,线程会直接跳过条件重检,继续执行后续逻辑,导致状态错乱。例如:
多个消费者同时 wait 在 num == 0 条件上,notifyAll() 后全部唤醒,但只有第一个抢到锁的能消费成功;其余线程若用 if,会误以为还有面可吃,接着执行 num--,造成负数。
每次被唤醒后,都重新判断条件是否真正成立,不成立就继续 wait:
synchronized(lock) {
while (!conditionMet) {
lock.wait();
}
// 安全执行业务逻辑
}
光用 while 不够,还需确保:
基本上就这些。不复杂但容易忽略,只要坚持 while + synchronized + notifyAll 组合,就能稳住生产者-消费者这类经典模型。