I am trying to create single variable producer consumer solution , but I am getting IllegalMonitorStateException in Producer's notifyAll() method. I am acquiring the lock in synchronized block as well , what might have gone wrong ?
/**
* Write a description of class SingleProducerConsumer here.
*
* @author (your name)
* @version (a version number or a date)
*/
public class SingleProdCons
{
public static void main(String args[])
{
Integer x = 0;
Thread producer = new Thread(new Producer(x),"Producer");
Thread consumer = new Thread(new Consumer(x),"Consumer");
producer.start();
consumer.start();
}
}
class Producer implements Runnable
{
private Integer x;
Producer(Integer x)
{
this.x = x;
}
@Override
public void run()
{
synchronized(x)
{
while(x.equals(0)==false){
//The value of the variable has not been consumed yet , we should wait here till it gets consumed
try{
x.wait();
}catch(InterruptedException ie)
{
System.out.println("Caught Exception : "+ie.getMessage());
}
}
//Else initialze the variable and let it get used by the Consumer then
synchronized(x)
{
x=10;
x.notifyAll();
}
}
}
}
class Consumer implements Runnable
{
private Integer x;
Consumer(Integer x)
{
this.x = x;
}
@Override
public void run()
{
synchronized(x)
{
while(x.equals(0)==true)
{
//The value has not been put by the Producer thread yet hence we should wait here
System.out.println("We are before the method call of the wait on the x object");
try{
x.wait();
}catch(InterruptedException ie)
{
System.out.println("Caught the exception : "+ie.getMessage());
}
}
}
synchronized(x)
{
System.out.println("Consuming : "+x);
x.notifyAll();
}
}
}
Exception in thread "Producer" java.lang.IllegalMonitorStateException
at java.lang.Object.notifyAll(Native Method)
at Producer.run(SingleProdCons.java:55)
at java.lang.Thread.run(Thread.java:745)
Exception in thread "Producer" java.lang.IllegalMonitorStateException
at java.lang.Object.notifyAll(Native Method)
at Producer.run(SingleProdCons.java:55)
at java.lang.Thread.run(Thread.java:745)
Exception in thread "Producer" java.lang.IllegalMonitorStateException
at java.lang.Object.notifyAll(Native Method)
at Producer.run(SingleProdCons.java:55)
at java.lang.Thread.run(Thread.java:745)
Exception in thread "Producer" java.lang.IllegalMonitorStateException
at java.lang.Object.notifyAll(Native Method)
at Producer.run(SingleProdCons.java:55)
at java.lang.Thread.run(Thread.java:745)
This is the problem:
synchronized(x)
{
x=10;
x.notifyAll();
}
It's important to understand that you don't synchronize on a variable - you synchronize on an object. So you're modify the value of x
to refer to a different Integer
object, and you're then calling notifyAll
on that different object... from a thread which doesn't own the monitor for that object.
I'd strongly advise you not to use Integer
objects for synchronization at all. Ideally, use an object which isn't used for any other purpose - that makes it easier to reason about.
You can still have your x
variable, and document that it shouldn't be modified other than when the thread holds the appropriate lock - but make it independent from the lock itself.
See more on this question at Stackoverflow