You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

单生产者多消费者模型调用notify()时出现死锁/无限等待问题排查

为什么单生产者多消费者用notify()会导致死锁/无限等待?

嘿,这个问题我之前在调试并发代码时也踩过一模一样的坑,咱们来一步步拆解背后的原因:

核心问题:notify()唤醒的线程是随机的,无法保证唤醒目标

notify()的作用是从当前对象的等待池中随机唤醒一个线程,JVM完全不保证它会唤醒哪一个——这就给多消费者场景埋下了隐患。

举个最典型的死锁场景,假设我们的队列容量是1:

  1. 生产者生产了一个元素,队列满了,调用wait()进入等待状态。
  2. 消费者A获取到锁,消费掉元素,队列变空,调用notify()后释放锁。
  3. 这时候JVM随机唤醒了另一个消费者B,而不是生产者。
  4. 消费者B获取锁后检查队列,发现是空的,于是也调用wait()进入等待。
  5. 现在生产者还在等待,所有消费者也都在等待,整个系统彻底卡住,没有线程能继续推进——死锁就发生了。

为什么你会疑惑?因为忽略了线程调度的不确定性

你提到“生产者会继续执行”,但这个前提是生产者必须被唤醒才行。如果每次notify()都碰巧唤醒的是其他消费者,生产者就会一直被晾在等待队列里,永远没机会被唤醒,自然就出现了无限等待的情况。

怎么解决?

  • 优先用notifyAll()替代notify():notifyAll()会唤醒所有等待的线程,虽然看起来效率低一点,但能保证所有等待的线程都有机会检查队列状态。那些不需要被唤醒的线程(比如队列空时的消费者)会在重新获取锁后,再次检查条件并调用wait(),而生产者一定会被唤醒,继续生产流程。
  • 用高级并发工具类:比如java.util.concurrent.BlockingQueue,它已经封装了安全的等待唤醒逻辑,不需要你手动处理wait()/notify(),从根源上避免这类问题。

补充:什么时候notify()是安全的?

只有在严格的一对一生产者-消费者场景下(一个生产者线程,一个消费者线程),notify()才是安全的——因为等待池中只有对方线程,唤醒的一定是目标线程。但只要线程数量超过2,尤其是多消费者或多生产者,notify()的随机性就会导致各种诡异的并发问题。

内容的提问来源于stack exchange,提问作者Nishant_Singh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 11:10:50