1. 手写生产者-消费者中 wait/notify 与 BlockingQueue 两种实现的虚假唤醒防御?
手写生产者-消费者,说明 wait/notify 与 BlockingQueue 两种实现,以及虚假唤醒防御?
- wait/notify 的 while 循环防御
- BlockingQueue 封装同步
- 条件变量与锁
wait/notify 实现:生产者等队列满(wait),生产后 notify;消费者等队列空(wait),消费后 notify。关键防御:wait 必须放在 while 循环中(while(buffer.isFull()) wait()),因为① 虚假唤醒(spurious wakeup)——线程可能无通知被唤醒;② 唤醒后需重新检查条件(notify 可能唤醒多个,条件可能已被其他线程改变)。BlockingQueue 实现:用 ArrayBlockingQueue/LinkedBlockingQueue,put 阻塞(满时)、take 阻塞(空时),内部已处理同步与等待,无需手写 wait/notify,更简单安全。生产者用 put、消费者用 take 即可。两者核心都是"条件等待 + 循环检查"。
虚假唤醒防御是并发手写的核心考点:wait 必须在 while 中而非 if 中,因为唤醒后不能假设条件仍成立。BlockingQueue 把条件等待与队列操作封装,规避手写 wait/notify 的错误。生产消费是"条件变量 + 同步容器"的经典应用。
// wait/notify 版本(生产者线程)
synchronized (buffer) {
while (buffer.size() == capacity) buffer.wait(); // while 防虚假唤醒
buffer.add(item);
buffer.notifyAll();
}
// 消费者
synchronized (buffer) {
while (buffer.isEmpty()) buffer.wait();
item = buffer.remove();
buffer.notifyAll();
}