在我的java程序中,当我编码
时synchronized(a){
a = 55;
a.wait();
}
它在java.lang.IllegalMonitorStateException
语句中提供运行时异常a.wait();
。但是a=55
成功运行。
但如果我编码为
synchronized(a){
a.wait();
a = 55;
}
然后它完美运行,没有任何异常。为什么呢?
答案 0 :(得分:3)
因为a
在重新分配后指向不同的对象,并且未进行同步。
换句话说,有两个对象val1
和val2
都分配给变量a
。您在val1
上进行同步,但在第一个示例中,请在val2
上调用等待。您使用的监视器附加到对象,而不是其变量。
因此,您应该通过引用非final变量来避免同步。这会导致你的困惑。如果该字段是可变的,请使用另一个锁,例如:
Object aMonitor = new Object();
synchronized(aMonitor) {
a = 55;
aMonitor.wait();
}
理想情况下,您的方案仅适用于学习。 wait()
和notify()
是原语,除非作为练习或构建自己的并发库,否则不应使用它们。如果是真实代码,请在java.util.concurrent
中使用更高级别的机制。
答案 1 :(得分:2)
因为您在执行作业时已替换了对象a
。这称为自动装箱。 a = 55
实际创建了一个新的Integer
对象,因此当您在其上调用a.wait()
时,它正在等待您未同步的另一个对象,这就是您获得异常的原因。< / p>
正如我在your other question的答案中提到的,您无法在synchronized
块内分配对象。即使是以下模式也是一个坏主意,因为您将a
分配给另一个对象,这意味着调用synchronized
的下一个线程将在不同的a
上执行此操作,因此2个线程可以同时在同一synchronized
块中。
synchronized(a){
a.wait();
// still a bad idea
a = 55;
}
答案 2 :(得分:0)
在第一种情况下,变量a(在分配给新整数之后)不是被synchronized(a)锁定的“a”,因此调用a.wait()会导致异常。