Search code examples
javamultithreadingillegalmonitorstateexcep

notify giving IllegalMonitorStateException


I have very poor knowledge on Multithreading.

I am expecting below Program to run perfectly, but it is not working and produces below Exception.

Exception in thread "Thread-1" java.lang.IllegalMonitorStateException
    at java.lang.Object.notify(Native Method)
    at com.onmobile.client.D.callD(Deadlock.java:76)
    at com.onmobile.client.B.run(Deadlock.java:50)
    at java.lang.Thread.run(Unknown Source)

Java File

public class Deadlock {
    C c = new C();
    D d = new D();

    public static void main(String[] args) {    
        new Deadlock();
    }

    public Deadlock() {
        A a = new A(d,c);
        B b = new B(d,c);

        Thread t1 = new Thread(a);
        Thread t2 = new Thread(b);

        t1.start();
        t2.start();
    }
}

class A implements Runnable{
    D dObj;
    C cObj;

    A(D obj, C obj1){
        this.dObj = obj;
        this.cObj = obj1;
    }
    @Override
    public void run() {
        cObj.callC(dObj);
    }
}



class B implements Runnable{
    D dObj;
    C cObj;

    B(D obj, C obj1){
        this.dObj = obj;
        this.cObj = obj1;
    }
    @Override
    public void run() {
        dObj.callD(cObj);
    }
}


class C{
    public synchronized void callC(D dObj){
        try {
            this.wait();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        dObj.callD1();
    }
    public synchronized void callC1(){
    }   
}

class D{
    public synchronized void callD(C cObj){
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }       
        cObj.callC1();
        cObj.notify();
    }

    public synchronized void callD1(){
    }   
}

I thought inside callC() method, object of class C ie cObj goes in waiting state and meanwhile control will go to callD() method and there it invokes cObj.notify(); So, this will awake waiting threads waiting on object cObj.

but it is giving me Exception. I think solution to my problem can be : Java: IllegalMonitorStateException on notify()

but I am not understanding it correctly.

Please guide me where I am going wrong.


Solution

  • If you want to notify or wait on an object, your thread must own the monitor of the object you act on.

    public synchronized void callD(C cObj){
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }       
        cObj.callC1();
        cObj.notify();
    }
    

    In this code section you synchronize on the instance of class D, as synchronized methods always obtain the monitor of the object they "live" on. But to be able to use cObj.notify() you have to obtain the monitor of the cObj instance, e.g. by doing

    synchronized(cObj) {
       cObj.notify();
    }