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