In the below code, when I execute the producercon
class, sometimes the execution stucks, looks like a deadlock. But if i make the get_flag ()
synchronized then there are no such problems.
I cannot figure out how there can be a problem. the flag
can either true or false so only one of the producer
or consumer
will get into the if
statement. After one of them enters the if
it will enter the monitor with object r
(both are initialized with the same object reference). The only problem which can happen that the r
object being modified by the increment_decrement ()
function call, and the get_flag ()
reading the flag at the same time, but even then it will not enter the if
in that iteration, but it will enter the if
block on the next iteration, and even if the first thread did not leave the monitor, it will wait there for it (before the synchronized
block).
How, and why is the program halting/hanging if get_flag ()
is not made synchronized
?
import java.io.*;
class resource
{
private boolean res, flag;
resource ()
{
flag=false;
}
boolean get_flag ()
{
return flag;
}
void increment_decrement (String s,boolean t)
{
res=t;
flag=t;
try
{
System.out.print("\n"+s+":"+res);
Thread.sleep(200);
}
catch(InterruptedException e)
{
}
}
}
class producer implements Runnable
{
resource r1;
Thread t1;
producer(resource r)
{
r1 = r;
t1 = new Thread(this);
t1.start();
}
public void run ()
{
while (true)
{
if(r1.get_flag () == false)
{
synchronized(r1)
{
r1.increment_decrement("Producer",true);
}
}
}
}
public void waitForThread () throws InterruptedException
{
t1.join ();
}
}
class consumer implements Runnable
{
resource r2;
Thread t2;
consumer(resource r)
{
r2 = r;
t2 = new Thread (this);
t2.start();
}
public void run()
{
while (true)
{
if(r2.get_flag () == true)
{
synchronized(r2)
{
r2.increment_decrement("Consumer",false);
}
}
}
}
public void waitForThread () throws InterruptedException
{
t2.join ();
}
}
public class producercon
{
public static void main(String args[])
{
try
{
System.out.print("PRESS CTRL+C TO TERMINATE\n");
resource r = new resource();
consumer c = new consumer(r);
producer p = new producer(r);
c.waitForThread ();
p.waitForThread ();
}
catch(InterruptedException e)
{
}
}
}
Your call to get_flag() is not thread safe nor volatile. This means in the cache of thread 1 it can be true while in the cache of thread 2 it can be false.
You need to make your boolean either volatile
or an AtomicBoolean
. Right now multiple threads are trying to access the boolean that is in no way synchronized.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With