尽管从同步上下文调用了 notifyAll(),但 IllegalMonitorStateException [英] IllegalMonitorStateException despite calling notifyAll() from synchronised context

查看:59
本文介绍了尽管从同步上下文调用了 notifyAll(),但 IllegalMonitorStateException的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

public class Alternate {
    static Boolean mutex = true;
    public static void main(String[] args) {
        Thread t1 = new Thread(new Odd(mutex));
        Thread t2 = new Thread(new Even(mutex));
        t1.start();
        t2.start();
    }
}

class Odd implements Runnable{
    Boolean mutex;

    Odd( Boolean mutex){
        this.mutex=mutex;   
    }

    @Override
    public void run() {
        try {
            synchronized(mutex){
                while(mutex){
                    mutex.wait();
                }
                System.out.println("odd");
                mutex=true;
                mutex.notifyAll();
                Thread.sleep(500);
            }
        }catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

class Even implements Runnable{
    Boolean mutex;

    Even( Boolean mutex){
        this.mutex=mutex;
    }

    @Override
    public void run() {
        try {
            synchronized(mutex){
                while(!mutex){
                    mutex.wait();
                }
                System.out.println("even");
                mutex=false;
                mutex.notifyAll();
                Thread.sleep(500);
            }
        }catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

错误是

java.lang.IllegalMonitorStateException
    at java.lang.Object.notifyAll(Native Method)
    at com.test.concurrency.Even.run(Alternate.java:55)
    at java.lang.Thread.run(Thread.java:722)

我无法找出错误的原因.我正在从同步上下文调用 notifyAll() 并从正确的对象调用它.

I am not able to figure out the reason for the error. I am calling notifyAll() from synchronised context and calling it from the correct object.

推荐答案

您正在更改线程下的锁定.每次你将布尔值设置为某个东西时,它就是一个不同的对象;代码

You're changing the lock out from under your threads. Every time you set your boolean to something, that's a different object; the code

            mutex=true;
            mutex.notifyAll();

将互斥锁设置为与线程同步的对象不同的对象(因此线程尚未为其获取监视器),然后它在新对象上调用 notifyAll.

sets mutex to a different object from the one the thread synchronized on (so the thread hasn't acquired the monitor for it), then it calls notifyAll on the new object.

使用一个锁,不要改变它.

Use a single lock and don't change it.

锁定布尔值、数字包装器或字符串太容易出错,应该避免.您不仅会遇到所看到的错误,而且应用程序的其他不相关部分(可能由其他人按照相同的做法编写)可能会锁定同一个对象并导致神秘的问题.布尔值、数字包装器和字符串可用于 JVM 中的所有内容.最好使用范围受限的锁,以便应用程序中的任何其他内容都无法获取它.

Locking on Booleans, numeric wrappers, or Strings is too error-prone and should be avoided. Not only can you end up with the error you're seeing, but other unrelated parts of the application (maybe written by somebody else following the same practice) could be locking on the same object and causing mysterious problems. Booleans, number wrappers, and strings are available to everything in the JVM. It's better to use a lock that is constrained in scope so that nothing else in your application can acquire it.

通常最好使用专用锁,您不将其用于任何其他目的.重载具有不同用途的东西很容易引起麻烦.

Often it's best to use a dedicated lock, something you don't use for any other purpose. Overloading something with different uses can cause trouble too easily.

这篇关于尽管从同步上下文调用了 notifyAll(),但 IllegalMonitorStateException的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆