Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/311.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 在整数上同步时,为什么notifyAll()会引发IllegalMonitorStateException?_Java_Synchronization_Notify_Illegalmonitorstateexcep - Fatal编程技术网

Java 在整数上同步时,为什么notifyAll()会引发IllegalMonitorStateException?

Java 在整数上同步时,为什么notifyAll()会引发IllegalMonitorStateException?,java,synchronization,notify,illegalmonitorstateexcep,Java,Synchronization,Notify,Illegalmonitorstateexcep,为什么此测试程序会导致java.lang.IllegalMonitorStateException public class test { static Integer foo = new Integer(1); public static void main(String[] args) { synchronized(foo) { foo++; foo.notifyAll(); }

为什么此测试程序会导致
java.lang.IllegalMonitorStateException

public class test {
    static Integer foo = new Integer(1);
    public static void main(String[] args) {
        synchronized(foo) {
            foo++;
            foo.notifyAll();
        }
        System.err.println("Success");
    }
}
结果:

Exception in thread "main" java.lang.IllegalMonitorStateException
        at java.lang.Object.notifyAll(Native Method)
        at test.main(test.java:6)

您已经正确地注意到,必须从同步块调用
notifyAll

但是,在您的情况下,由于自动装箱,您同步的对象与您调用的
notifyAll
on的实例不同。事实上,新的、递增的
foo
实例仍然被限制在堆栈中,在
wait
调用中不可能阻止其他线程


您可以实现自己的可变计数器,在其上执行同步。根据您的应用程序,您可能还会发现它满足您的需要。

正如erickson所指出的,没有postincrement操作符的代码工作时不会出错:

static Integer foo = new Integer(1);

public static void main(String[] args) {
    synchronized (foo) {
        foo.notifyAll();
    }
    System.out.println("Success");
}
输出:

成功


您还应该警惕锁定或通知JVM可以插入的字符串和整数等对象(以防止创建大量表示整数1或字符串“”的对象)

下面是erickson在上面建议的AtomicInteger的一个实现。在本例中,foo.notifyAll();不会生成java.lang.IllegalMonitorStateException,因为在foo.incrementAndGet()时未刷新AtomicInteger对象;他跑了

输出:

foo is: 2

我没有意识到递增整数将分配一个新对象,而不是更改现有对象的值。尝试使用枚举等待/通知也会导致以下情况:
synchronized(myEnum){myEnum=myEnum.new_value;myEnum.notify();}
对于那些寻找布尔值解决方案的人,使用AtomicBoolean作为包装器type@dmitrii,确实是的,但是这里您要显式地修改引用。这不仅适用于枚举,而且适用于任何对象引用。使用基本类型包装器作为同步器和条件数据是非常诱人的。真是个错误!
foo is: 2