在我的java程序,当我的代码凡调用wait()
synchronized(a){
a = 55;
a.wait();
}
它详细介绍了a.wait();
声明运行时异常java.lang.IllegalMonitorStateException
。但a=55
成功运行。
但是,如果我的代码为
synchronized(a){
a.wait();
a = 55;
}
然后它完美地运行没有任何异常。为什么这样?
在我的java程序,当我的代码凡调用wait()
synchronized(a){
a = 55;
a.wait();
}
它详细介绍了a.wait();
声明运行时异常java.lang.IllegalMonitorStateException
。但a=55
成功运行。
但是,如果我的代码为
synchronized(a){
a.wait();
a = 55;
}
然后它完美地运行没有任何异常。为什么这样?
因为a
在重新分配后指向一个不同的对象,并且未被同步。
换句话说,有两个对象val1
和val2
都被分配给变量a
。您在val1
上同步,但在第一个示例中呼叫等待val2
。您使用的显示器附加到对象,而不是其变量。
因此,您应该避免通过引用非最终变量来进行同步。这会导致你的困惑。如果该字段是可变的,用另一把锁,例如:
Object aMonitor = new Object();
synchronized(aMonitor) {
a = 55;
aMonitor.wait();
}
理想的情况下您的方案只是为了学习,但。 wait()
和notify()
是原语,除非作为练习或构建自己的并发库,否则不应使用它。如果是真码,请在java.util.concurrent
中使用更高级别的机制。
因为您在完成任务时已替换了对象a
。这被称为自动装箱。 a = 55
实际上会创建一个新的Integer
对象,因此当您对其调用a.wait()
时,它正在等待您不同步的对象,这就是为什么您会遇到异常。
正如我在your other question的回答中所述,您不能在块内分配对象。即使是下面的模式也是一个坏主意,因为那么您将a
分配给不同的对象,这意味着下一个要调用的线程将在不同的a
上这样做,因此2个线程可以同时在相同的块中。
synchronized(a){
a.wait();
// still a bad idea
a = 55;
}
在第一种情况,变量a(分配给新的整数后)没有“一”一个已经通过同步的(a)中,因此调用a.wait(锁定)导致异常。