The below program is a simple threaded program . For some reason which i am not able to figure , its getting stuck at infinite loop of both produce() and consume() methods simultaneously in both the threads.
It produces the output for a few times and then there is no output at the console. So I presume its getting stuck at the loop.
My question is , since the loop depends on the value of the flag valueSet
of the same object of Item class , valueSet
can't be both true and false at the same time . So either of the produce() or cosume() method's loop should get false and the printing of output should continue.
But that's not happening here. So why is it getting stuck at the while loop if the condition depends on the flag variable which can only take true or false at a time ?
class Item{
boolean valueSet = false ;
int item = 0 ;
public void consume(){
while(!valueSet) ;
System.out.println("Consumed : " + item ) ;
valueSet = false ;
}
public void produce(int n ){
while(valueSet);
item = n ;
System.out.println("Produced : " + item ) ;
valueSet = true ;
}
}
class Producer implements Runnable{
Item item ;
Producer(Item itemobj){
item = itemobj ;
}
public void run(){
while(true){
System.out.println("\nProducing ....") ;
item.produce((int)Math.random()*100) ;
}
}
}
class Consumer implements Runnable{
Item item ;
Consumer(Item itemobj){item = itemobj ; }
public void run(){
while(true){
System.out.println("\nConsuming !") ;
item.consume() ;
}
}
}
class Main{
public static void main(String[] args) {
Item item = new Item() ;
Thread consumer = new Thread(new Consumer(item)) ;
Thread producer = new Thread(new Producer(item)) ;
System.out.println("\nStarted producer and consumer threads : ") ;
consumer.start() ;
producer.start() ;
}
}
Update :
When the while(valueSet)
is stuck at infinite loop in one thread , shouldn't while(!valuSet)
get out of loop and flip the valueSet
? This would inturn cause while(valueSet)
to come out of loop right ?
As per some answers it seems when while(valueSet)
is stuck , the other thread is somehow not able to access valueSet
. I don't understand how this is happening. Please explain your answer.
I see that using volatile
for valueSet
will fix it but i am not able to understand how without using it. It's causing the infinite loop even if it depends on one flag valueSet
which can't be true and false at the same time.
Basically, what you're trying to do here is to use valueSet
as a boolean flag to synchronize the Consumer
and Producer
-- to make them work in turn. It is true that valueSet
can only be true or false at one moment; however, it's not how the two threads (Consumer and Producer) view it.
We know that in Java, objects are stored on the heap; that is called the main memory. For each thread, however, for performance's sake, references to used objects are kept in a thread-specific cache. As in here, Producer
and Consumer
share one Item
object which is stored on the heap; the field item.valueSet
might be cached by each thread.
_______________ ______________
| Consumer | | Producer |
| _________ | | _________ |
| | | | | | | |
| | Cache1 | | | | Cache2 | |
| | valueSet| | | | valueSet| |
| |_________| | | |_________| |
|_______________| |______________|
| | | |
| | | |
_|_|______________|_|__
| |
| MAIN MEMORY |
| valueSet |
|_______________________|
When, say, Consumer
changes valueSet
to false
, it might or might not flush the new value to the main memory; similarly, when Producer
checks valueSet
, it might or might not try to read the newest value from the main memory. That's where the volatile
keyword comes into play. When you set valueSet
to be volatile
, it ensures that both threads write/read the newest value to/from main memory.
Notice that the above summary is bascially known as the JVM Memory Model. It's a set of rules to define JVM's behaviour under multithreading situations.
If you try changing the following parts of your code:
**volatile** boolean valueSet = false ;
**volatile** int item = 0 ;
...
item.produce((int)(Math.random()*100)) ; // added parenthesis
You will see following output:
Started producer and consumer threads :
Consuming !
Producing ....
Produced : 83
Producing ....
Consumed : 83
Consuming !
Produced : 54
Producing ....
Consumed : 54
Consuming !
Produced : 9
Producing ....
Consumed : 9
Consuming !
Produced : 23
Producing ....
Consumed : 23