Java 为什么notifyAll() 在Integer 上同步时会引发IllegalMonitorStateException?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/260337/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Why does notifyAll() raise IllegalMonitorStateException when synchronized on Integer?
提问by jjvainio
Why does this test program result in a java.lang.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");
}
}
Result:
结果:
Exception in thread "main" java.lang.IllegalMonitorStateException
at java.lang.Object.notifyAll(Native Method)
at test.main(test.java:6)
采纳答案by erickson
You have noted correctly that notifyAll
must be called from a synchronized block.
您已经正确地注意到notifyAll
必须从同步块中调用。
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, incremented foo
instance is still confined to the stack, and no other threads could possibly be blocked on a wait
call.
但是,在您的情况下,由于自动装箱,您同步的对象与您调用的实例不同notifyAll
。事实上,新的、递增的foo
实例仍然被限制在堆栈中,并且没有其他线程可能在wait
调用时被阻塞。
You could implement your own, mutable counter on which synchronization is performed. Depending on your application, you might also find that AtomicIntegermeets your needs.
您可以实现自己的可变计数器,在该计数器上执行同步。根据您的应用程序,您可能还会发现AtomicInteger满足您的需求。
回答by matt b
As erickson has noted, the code without the postincrement operator works without error:
正如 erickson 所指出的,没有后增量运算符的代码可以正常工作:
static Integer foo = new Integer(1);
public static void main(String[] args) {
synchronized (foo) {
foo.notifyAll();
}
System.out.println("Success");
}
output:
输出:
Success
成功
回答by dbt
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 "").
您还应该警惕锁定或通知诸如 String 和 Integer 之类的可以由 JVM 驻留的对象(以防止创建大量表示整数 1 或字符串“”的对象)。
回答by Eric Leschinski
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.
递增 Integer 会使旧的 foo 消失并被一个全新的对象 foo 替换,该对象与之前的 foo 变量不同步。
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.
这是 erickson 上面建议的 AtomicInteger 的一个实现。在这个例子中 foo.notifyAll(); 不会产生 java.lang.IllegalMonitorStateException 因为当 foo.incrementAndGet() 时 AtomicInteger 对象没有刷新;正在运行。
import java.util.concurrent.atomic.AtomicInteger;
public class SynchronizeOnAPrimitive {
static AtomicInteger foo = new AtomicInteger(1);
public static void main(String[] args) {
synchronized (foo) {
foo.incrementAndGet();
foo.notifyAll();
}
System.out.println("foo is: " + foo);
}
}
Output:
输出:
foo is: 2