Java 同步:IllegalMonitorStateException

时间:2020-12-23 21:36:10

标签: java

我不知道为什么程序出错了,它抛出IllegalMonitorStateException 同步

为什么我无法获得监视器对象??

public class Test extends Thread{
    
    Boolean flag = false ;
    
    @Override
    public void run() {
        while( true ) {
            try {
                Thread.sleep(10) ;
            }catch (Exception e) {}
        }
    }
    
    public void change() {
        synchronized (flag ) {
            flag = true ;
            flag.notifyAll();
        }
    }
    
    public static void main(String[] args) {
        Test test = new Test() ;
        test.start();
        test.change();
    }

}

1 个答案:

答案 0 :(得分:0)

您似乎误解了 java 的工作原理。您将一些语言功能混合在一起,因此导致混淆是有道理的。

<块引用>

Boolean flag = false ;

这是语法糖:

Boolean flag = Boolean.valueOf(false);

flag 是一个指针(好吧,它是 java,我们称它为引用。potayto potahto)。 flag 当前指向一个全局常量布尔值(系统在启动时生成 2 个布尔对象以提高效率)。

<块引用>

synchronized (flag) {

哦,亲爱的。不要那样做。永远不要锁定公开的东西。这不会锁定“标志”,而是锁定标志指向的事物。哪个是全局 false 布尔值。

<块引用>

flag = true;

好的,现在 flag 指向全局 true

<块引用>

flag.notifyAll();

那是无效的;除非您有锁定,否则您无法通知某事。您在这里锁定了全局 false,而不是全局 true。

但是您既不想锁定全局对象,也不想通知全局对象,因此这一点没有实际意义。

不过,它确实可以解释您的错误。

好的,那我该怎么办?

创建一个私有对象。确保变量只指向一件事。 AtomicBoolean 做到了这一切。只需将 Boolean flag = false 替换为 AtomicBoolean flag = new AtomicBoolean();,将 flag = true 替换为 flag.set(true),至关重要的是,这只是更改所指向对象的属性,而不是更改指针。

请注意,synchronized 是完全没有意义的,除非其他一些代码试图锁定同一事物(synchronized(x) 这样做,其中 x 指向与您正在同步的任何事物相同的事物。

相关问题