为什么此测试程序会产生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)
答案 0 :(得分:54)
您已正确注意到必须从同步块中调用notifyAll
。
但是,在您的情况下,由于自动装箱,您同步的对象与您在notifyAll
上调用的实例不同。实际上,新的递增foo
实例仍然局限于堆栈,并且在wait
调用中不可能阻止其他线程。
您可以实现自己的可变计数器,在该计数器上执行同步。根据您的应用程序,您可能还会发现AtomicInteger符合您的需求。
答案 1 :(得分:3)
你也应该谨慎地锁定或通知可以由JVM实现的String和Integer之类的对象(以防止创建大量表示整数1或字符串“”的对象。
答案 2 :(得分:3)
增加整数会使旧的foo消失并被替换为与前一个foo变量不同步的全新对象foo。
以下是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);
}
}
输出:
foo is: 2
答案 3 :(得分:1)
正如erickson所指出的那样,没有postincrement运算符的代码可以正常工作:
static Integer foo = new Integer(1);
public static void main(String[] args) {
synchronized (foo) {
foo.notifyAll();
}
System.out.println("Success");
}
输出:
成功