Java中mutex.wait()与mutex.notify()时序异常问题排查
生产者-消费者模型异常问题解答
不是wait/notify延迟,是线程调度的偏向性问题
你的代码逻辑没问题,但出现这种“生产者等库存空、消费者等库存满”的极端情况,根源是操作系统线程调度器的调度偏向,和wait/notify的响应延迟没关系。
具体触发过程
- 生产者把库存填满到100,调用
notify()后退出同步块。但线程调度器为了减少上下文切换开销,大概率会让刚释放锁的生产者线程再次抢到mutex_stock锁。此时生产者检查库存已满,直接进入wait状态,释放锁。 - 消费者抢到锁后消费一部分,调用
notify()退出同步块,同样的,调度器又可能让消费者再次拿到锁。消费者一看库存还没清零,继续消费,直到库存空了才会进入wait,这时候生产者才有机会重新运行。
加sleep后恢复正常的原因
同步块后加Thread.sleep(50),相当于让当前线程主动让出CPU时间片,给另一个线程留足抢锁的机会,直接打破了调度器的偏向性,两个线程就能交替执行,符合你预期的逻辑。
另一种验证方式
你可以把sleep换成Thread.yield()(仅提示调度器切换线程,不强制休眠),也能大概率恢复正常——这进一步说明问题出在调度器,不是wait/notify的延迟。
补充说明:wait/notify本身是即时的
调用notify()后,等待队列里的一个线程会被移到同步队列,只要锁一释放,这个线程就有机会抢锁执行。至于它什么时候能抢到锁,完全由操作系统调度器决定,和wait/notify本身的机制无关。
内容的提问来源于stack exchange,提问作者Christoph Linden
相关产品推荐
相关产品推荐

