Pergunta

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.

Foi útil?

Solução 2

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();
}

Outras dicas

when calling object.notify, you must be holding the the lock for that exact object, ie:

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

you should also wrap your wait call in a similar synchronized block:

synchronized(cObj) {
   cObj.wait()
}

I suggest you read more about it in the Java tutorial: http://docs.oracle.com/javase/tutorial/essential/concurrency/

notify on an Object should be called only after taking lock or synchronizing on that object. So in your case what you need is:

class D{
    public void callD(C cObj){ //synchronized not required here
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }   
        synchronize(cObj) {  //synchornize here on cObj  
           cObj.callC1();
           cObj.notify();
        }
    }
}

Note: in case you are change your code to synchornize callD and synchroniz(cObj) make sure you on deadlock scenario. IMHO only synchroniz(cObj) should suffice.

To call notify() on an object you need to you own this object's lock. In this case to call

cObj.notify();

you need to wrap it into syncronized block like this:

syncronized (cObj)
{
    cObj.notify();
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top