我对多线程知识很差。

我期望下面的程序能够完美运行,但是它无法正常工作,并且会在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文件

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

但我对它的理解不正确。

请指导我哪里出问题了。

最佳答案

如果要通知或等待对象,则线程必须拥有您要操作的对象的监视器。

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

07-24 20:49