简体   繁体   English

通知给IllegalMonitorStateException

[英]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以下产生。

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

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(); 我认为在callC()方法内部,类C的对象即cObj进入等待状态,同时控制将转到callD()方法,并在那里调用cObj.notify();。 So, this will awake waiting threads waiting on object cObj. 因此,这将唤醒等待对象cObj的等待线程。

but it is giving me Exception. 但这给了我例外。 I think solution to my problem can be : Java: IllegalMonitorStateException on notify() 我认为我的问题的解决方案可以是: Java:notify()上的IllegalMonitorStateException

but I am not understanding it correctly. 但我对它的理解不正确。

Please guide me where I am going wrong. 请指导我哪里出问题了。

when calling object.notify, you must be holding the the lock for that exact object, ie: 调用object.notify时,必须持有该确切对象的锁,即:

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/ 我建议您在Java教程中阅读有关它的更多信息: http : //docs.oracle.com/javase/tutorial/essential/concurrency/

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. 在此代码部分中,您将在类D的实例上进行同步,因为已同步的方法始终会获取其“活动”对象的监视器。 But to be able to use cObj.notify() you have to obtain the monitor of the cObj instance, eg by doing 但是要使用cObj.notify()您必须获取cObj实例的监视器,例如通过

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

notify on an Object should be called only after taking lock or synchronizing on that object. 只有在对该对象进行锁定或synchronizing之后,才应在该Object上进行notify 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. 注意:如果要更改代码以synchornize callDsynchroniz(cObj)确保处于deadlock情况。 IMHO only synchroniz(cObj) should suffice. 恕我直言,仅synchroniz(cObj)就足够了。

To call notify() on an object you need to you own this object's lock. 要在对象上调用notify() ,您需要拥有该对象的锁。 In this case to call 在这种情况下打电话

cObj.notify();

you need to wrap it into syncronized block like this: 您需要像这样将其包装到同步块中:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM