猿问

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

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

我对输出有一些疑问:

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

Producer t1 has lock

t5 produced 1, integerQueue: [1]

Producer t5 notifiedAll

我认为所有线程都应该竞争锁,并且应该最多有一个线程一直拥有锁?所有生产者都共享锁吗?当生产者线程 t1 持有锁时,消费者线程 t5 如何获得锁?

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


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

似乎除了一个生产者和消费者之外的所有线程都已死亡,并且这两个线程正在彼此之间切换锁。为什么会发生这种情况?所有其他生产者和消费者发生了什么?

任何帮助是极大的赞赏。


弑天下
浏览 149回答 1
1回答

慕后森

您正在使用可运行对象的单个实例Producer5,并将其多次提交给执行服务。    Producer5 producer = new Producer5(queue, maxCapacity);    pool.execute(producer);    pool.execute(producer);    pool.execute(producer);    pool.execute(producer);    pool.execute(producer);因此,threadName该单个实例中的字段Producer5将被覆盖多次并且没有用(它将不再打印出实际正在运行的线程的名称,此外,它需要被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如果同一实例包含可变状态,请勿重复使用该实例。为每个执行线程创建一个单独的实例。当生产者线程 t1 持有锁时,消费者线程 t5 如何获得锁?仍然是线程 t1 运行此代码,但该threadName字段同时已由线程 t5 更新。高度误导性的输出。似乎除了一个生产者和消费者之外的所有线程都已死亡,并且这两个线程正在彼此之间切换锁。线程都仍然处于活动状态,但只有两个threadName字段存在,线程轮流更新它们(在方法的顶部run),最终确定某个值。所有线程现在只打印该值。
随时随地看视频慕课网APP

相关分类

Java
我要回答