0

我对多线程的了解很差。

我期望下面的程序可以完美运行,但它不工作并产生以下异常。

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

4 回答 4

4

调用 object.notify 时,您必须持有该确切对象的锁,即:

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

您还应该将您的等待调用包装在类似的同步块中:

synchronized(cObj) {
   cObj.wait()
}

我建议您在 Java 教程中阅读更多相关信息:http: //docs.oracle.com/javase/tutorial/essential/concurrency/

于 2013-10-22T08:06:27.950 回答
0

如果你想通知或等待一个对象,你的线程必须拥有你操作的对象的监视器。

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

在此代码部分中,您将在 class 的实例上进行D同步,因为同步方法始终获取它们“生存”的对象的监视器。但是为了能够使用cObj.notify()你必须获得cObj实例的监视器,例如通过做

synchronized(cObj) {
   cObj.notify();
}
于 2013-10-22T08:06:34.380 回答
0

notifyon anObject应该只在获得锁定或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 callDsynchroniz(cObj)确保您在deadlock场景中。恕我直言synchroniz(cObj),就足够了。

于 2013-10-22T08:06:58.583 回答
0

要调用notify()一个对象,您需要拥有该对象的锁。在这种情况下调用

cObj.notify();

你需要像这样将它包装到同步块中:

syncronized (cObj)
{
    cObj.notify();
}
于 2013-10-22T08:11:16.150 回答