0
votes

I'm working on the multiple producer and consumer use case of Producer-Consumer problem with Java. The code is on github. The same implementation worked for the single producer consumer use case, but behaved weirdly for the multiple producer consumer case.

I have some questions regarding the output:

At the start, all producers and one consumer has the lock:

Producer t1 has lock
t5 produced 1, integerQueue: [1]
Producer t5 notifiedAll
  1. I thought all threads should compete for the lock and there should be at most one thread that has the lock of all time? Are all producers sharing the lock? How did consumer thread t5 get the lock while producer thread t1 was holding it?

After it runs for a while, another weird phenomenon appears:

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. It seems all threads except one producer and consumer had died and those 2 are switching lock between each other. Why is this happening? What happened to all the other producers and consumers?

Any help is greatly appreciated.

1
Yes, my mistake.fall

1 Answers

1
votes

You are using a single instance of your Producer5 runnable and submit it many times to the execution service.

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

So your threadName field in that single Producer5 instance will get overwritten several times and is not useful (it will no longer print out the name of the thread that is actually running, furthermore it would need to be volatile in order to be updated properly by multiple threads -- for some definition of properly).

  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 
  )); 

Do not re-use the same Runnable instance if it contains mutable state. Make a separate instance for each thread of execution.


How did consumer thread t5 get the lock while producer thread t1 was holding it?

It was still Thread t1 running this code, but the threadName field has in the mean-time been updated by Thread t5. Highly misleading output.

It seems all threads except one producer and consumer had died and those 2 are switching lock between each other.

The threads are all still alive, but there are only two threadName fields in existence, that the threads have been taking turns to update (at the top of the run method), finally settling on some value. All threads just print that value now.