为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

弑天下 2023-08-23 10:36:38
我正在研究 Java 的生产者-消费者问题的多个生产者和消费者用例。代码在github上。相同的实现适用于单个生产者消费者用例,但对于多个生产者消费者用例表现得很奇怪。我对输出有一些疑问:一开始,所有生产者和一个消费者都拥有锁:Producer t1 has lockt5 produced 1, integerQueue: [1]Producer t5 notifiedAll我认为所有线程都应该竞争锁,并且应该最多有一个线程一直拥有锁?所有生产者都共享锁吗?当生产者线程 t1 持有锁时,消费者线程 t5 如何获得锁?运行一段时间后,又出现了一个奇怪的现象:Producer t5 has lockt5 produced 10, integerQueue: [8, 9, 10]Producer t5 notifiedAllProducer t5 has lockt5 produced 11, integerQueue: [8, 9, 10, 11]Producer t5 notifiedAllConsumer t8 has lockt8 consumed 8, integerQueue: [9, 10, 11]Consumer t8 notified AllConsumer t8 has lockt8 consumed 9, integerQueue: [10, 11]Consumer t8 notified All似乎除了一个生产者和消费者之外的所有线程都已死亡,并且这两个线程正在彼此之间切换锁。为什么会发生这种情况?所有其他生产者和消费者发生了什么?任何帮助是极大的赞赏。
查看完整描述

1 回答

?
慕后森

TA贡献1802条经验 获得超5个赞

您正在使用可运行对象的单个实例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),最终确定某个值。所有线程现在只打印该值。


查看完整回答
反对 回复 2023-08-23
  • 1 回答
  • 0 关注
  • 148 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信