为什么在 Integer 上同步时,notifyAll() 会引发 IllegalMonitorStateException?
为什么这个测试程序会导致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)
Why does this test program result in a 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");
}
}
Result:
Exception in thread "main" java.lang.IllegalMonitorStateException
at java.lang.Object.notifyAll(Native Method)
at test.main(test.java:6)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
您已经正确地注意到,
notifyAll
必须从同步块调用。但是,在您的情况下,由于自动装箱,您同步的对象不是您调用
notifyAll
的同一实例。 事实上,新的、递增的foo
实例仍然限制在堆栈中,并且任何其他线程都不可能在wait
调用上被阻塞。您可以实现自己的可变计数器,并在其上执行同步。 根据您的应用程序,您可能还会发现 AtomicInteger 满足您的需求。
You have noted correctly that
notifyAll
must be called from a synchronized block.However, in your case, because of auto-boxing, the object you synchronized on is not the same instance that you invoked
notifyAll
on. In fact, the new, incrementedfoo
instance is still confined to the stack, and no other threads could possibly be blocked on await
call.You could implement your own, mutable counter on which synchronization is performed. Depending on your application, you might also find that AtomicInteger meets your needs.
您还应该对锁定或通知诸如 String 和 Integer 等可以被 JVM 保留的对象保持警惕(以防止创建大量表示整数 1 或字符串“”的对象)。
You should also be leery of locking or notifying on objects like String and Integer that can be interned by the JVM (to prevent creating a lot of objects that represent the integer 1 or the string "").
增加 Integer 会使旧的 foo 消失并被一个全新的对象 foo 取代,该对象与之前的 foo 变量不同步。
这是埃里克森上面建议的 AtomicInteger 的实现。 在此示例中 foo.notifyAll(); 不会产生 java.lang.IllegalMonitorStateException 因为 AtomicInteger 对象在 foo.incrementAndGet(); 时没有刷新; 正在运行。
输出:
Incrementing the Integer makes the old foo disappear and be replaced with a brand new object foo which is not synchronized with the previous foo variable.
Here is an implementation of AtomicInteger that erickson suggested above. In this example foo.notifyAll(); does not produce a java.lang.IllegalMonitorStateException beause the AtomicInteger Object is not refreshed when foo.incrementAndGet(); is run.
Output:
正如埃里克森所指出的,没有后增量运算符的代码可以正常工作,不会出现错误:
输出:
As erickson has noted, the code without the postincrement operator works without error:
output: