Уведомить, давая IllegalMonitorStateException

У меня очень плохие знания по многопоточности.

Я ожидаю, что нижеприведенная Программа будет работать отлично, но она не работает и выдает ниже Исключения.

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

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

Я думал, что внутри метода callC() объект класса C, т.е. cObj переходит в состояние ожидания, а управление переходит в метод callD() и там он вызывает cObj.notify(); Таким образом, это пробудит ожидающие потоки, ожидающие на объекте cObj.

но это дает мне исключение. Я думаю, что решение моей проблемы может быть: Java: IllegalMonitorStateException on notify ()

но я не правильно понимаю

Пожалуйста, ведите меня, где я иду не так.

4 ответа

Решение

Если вы хотите уведомить или подождать объекта, ваш поток должен иметь монитор объекта, с которым вы работаете.

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

В этом разделе кода вы синхронизируете на экземпляре класса DТак как синхронизированные методы всегда получают монитор объекта, на котором они "живут". Но чтобы иметь возможность использовать cObj.notify() Вы должны получить монитор cObj например, делая

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

При вызове object.notify вы должны удерживать блокировку для этого точного объекта, то есть:

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

Вы должны также обернуть свой ожидающий вызов в подобный синхронизированный блок:

synchronized(cObj) {
   cObj.wait()
}

Я предлагаю вам прочитать больше об этом в руководстве по Java: http://docs.oracle.com/javase/tutorial/essential/concurrency/

notify на Object следует вызывать только после взятия блокировки или synchronizing на этом объекте. Так что в вашем случае вам нужно:

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

Примечание: если вы измените свой код на synchornize callD а также synchroniz(cObj) убедитесь, что вы на deadlock сценарий. Только ИМХО synchroniz(cObj) должно хватить.

Звонить notify() на объекте вам нужно владеть замком этого объекта. В этом случае позвонить

cObj.notify();

вам нужно обернуть его в синхронизированный блок следующим образом:

syncronized (cObj)
{
    cObj.notify();
}
Другие вопросы по тегам