wait()的核心作用是让生产者线程在资源不可用时释放锁并暂停执行,必须与synchronized和notifyall()配合,置于while循环中检查条件,使用共享锁对象,以避免忙等、虚假唤醒和假死现象。

在多生产者场景下,wait() 的核心作用是让生产者线程在资源不可用时主动让出锁、暂停执行,避免忙等和资源浪费。它不是独立工作的,必须与 synchronized 和 notifyAll() 配合,形成“检查—等待—唤醒—再检查”的闭环逻辑。
必须放在 while 循环中检查条件
不能用 if 判断后调用 wait(),否则可能因虚假唤醒或竞争导致状态不一致。例如缓冲区已满时,多个生产者同时进入同步块,只靠一次 if (isFull()) wait(); 无法保证唤醒后条件仍成立。
- 正确写法:用
while (isFull()) wait();—— 唤醒后重新校验,确保真正可生产 - 常见错误:
if+wait()可能跳过二次检查,造成向满队列插入数据,抛出异常或破坏数据一致性
锁对象必须是共享资源本身或其保护对象
wait() 是对象级别的操作,调用前线程必须持有该对象的监视器锁。生产者之间要协作,就得共用同一个锁对象(如缓冲区实例、队列对象或显式定义的 Object lock = new Object();)。
Java Maven 项目审查工作流的通用输入处理。当 Java Maven 项目以 ZIP压缩包或 GitLab 仓库 URL 形式提供且需要...时使用。
- 所有生产者和消费者都对同一对象调用
wait()和notifyAll(),才能确保彼此可见、互相唤醒 - 若各自使用不同锁对象(比如每个线程 new 一个 lock),
wait()将永远无法被正确唤醒
配合 notifyAll() 避免假死
多生产者+多消费者环境下,仅用 notify() 极易唤醒同类线程(比如唤醒另一个生产者),而真正需要的消费者却一直等待,导致双方都卡住——即“假死”现象。
- 生产者完成一次入队后,应调用
lock.notifyAll(),通知所有等待中的生产者和消费者重新竞争 - 消费者消费后同样调用
notifyAll(),确保可能阻塞的生产者也能及时恢复 - 虽然开销略大,但语义清晰、行为可预测,是多角色协作的稳妥选择
wait() 会释放锁,这是协作的前提
关键机制在于:wait() 立即释放当前持有的锁,使其他线程(尤其是消费者)能进入同步块修改状态(如取走数据)、再调用 notifyAll()。
- 如果
wait()不释放锁,消费者永远拿不到锁,就无法消费,生产者也永远等不到空间,系统彻底僵死 - 线程被唤醒后,需重新竞争锁;获得锁后才从
wait()返回,继续执行后续逻辑
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










