多生产者和消费者多线程 Java 无法按预期工作



我正在研究Java的生产者-消费者问题的多个生产者和消费者用例。代码在 github 上。相同的实现适用于单个生产者使用者用例,但对于多生产者使用者用例,行为很奇怪。

我对输出有一些疑问:

一开始,所有生产者和一个消费者都有锁:

Producer t1 has lock
t5 produced 1, integerQueue: [1]
Producer t5 notifiedAll
  1. 我认为所有线程都应该竞争锁,并且最多应该有一个线程拥有有史以来的锁?所有生产者都在共享锁吗?消费者线程 t5 是如何在生产者线程 t1 持有它时获得锁的?

运行一段时间后,又出现了一个奇怪的现象:

Producer t5 has lock
t5 produced 10, integerQueue: [8, 9, 10]
Producer t5 notifiedAll
Producer t5 has lock
t5 produced 11, integerQueue: [8, 9, 10, 11]
Producer t5 notifiedAll
Consumer t8 has lock
t8 consumed 8, integerQueue: [9, 10, 11]
Consumer t8 notified All
Consumer t8 has lock
t8 consumed 9, integerQueue: [10, 11]
Consumer t8 notified All
  1. 似乎除了一个生产者和消费者之外的所有线程都已经死亡,而这两个线程正在彼此之间切换锁。为什么会这样?所有其他生产者和消费者发生了什么?

任何帮助将不胜感激。

您正在使用可运行的Producer5的单个实例,并将其多次提交到执行服务。

Producer5 producer = new Producer5(queue, maxCapacity);
pool.execute(producer);
pool.execute(producer);
pool.execute(producer);
pool.execute(producer);
pool.execute(producer);

因此,您在单个Producer5实例中的threadName字段将被多次覆盖并且没有用(它将不再打印出实际正在运行的线程的名称,此外,需要volatile它才能被多个线程正确更新 - 对于某些正确定义(。

System.out.println(String.format("nProducer %s has lock",
threadName // this will be the name of the last thread that entered `run`, 
// they all share the same instance 
)); 

如果同一Runnable实例包含可变状态,请不要重复使用该实例。为每个执行线程创建一个单独的实例。


消费者线程 t5 是如何在生产者线程 t1 持有它时获得锁的?

运行此代码的仍然是线程 t1,但线程 t5 同时更新了threadName字段。高度误导性的输出。

似乎除了一个生产者和消费者之外的所有线程都已经死亡,这两个线程正在彼此之间切换锁。

线程都还活着,但存在两个threadName字段,线程轮流更新(在run方法的顶部(,最终确定一些值。所有线程现在都只打印该值。

最新更新