IllegalMonitorStateException when sharing the object

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)
Jon Skeet
people
quotationmark

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.

people

See more on this question at Stackoverflow