2012-03-06 58 views
0

在我的java程序,当我的代码凡调用wait()

synchronized(a){ 
    a = 55; 
    a.wait(); 
} 

它详细介绍了a.wait();声明运行时异常java.lang.IllegalMonitorStateException。但a=55成功运行。

但是,如果我的代码为

synchronized(a){ 
    a.wait(); 
    a = 55; 
} 

然后它完美地运行没有任何异常。为什么这样?

回答

3

因为a在重新分配后指向一个不同的对象,并且未被同步。

换句话说,有两个对象val1val2都被分配给变量a。您在val1上同步,但在第一个示例中呼叫等待val2。您使用的显示器附加到对象,而不是其变量。

因此,您应该避免通过引用非最终变量来进行同步。这会导致你的困惑。如果该字段是可变的,用另一把锁,例如:

Object aMonitor = new Object(); 

synchronized(aMonitor) { 
    a = 55; 
    aMonitor.wait(); 
} 

理想的情况下您的方案只是为了学习,但。 wait()notify()是原语,除非作为练习或构建自己的并发库,否则不应使用它。如果是真码,请在java.util.concurrent中使用更高级别的机制。

2

因为您在完成任务时已替换了对象a。这被称为自动装箱。 a = 55实际上会创建一个新的Integer对象,因此当您对其调用a.wait()时,它正在等待您不同步的对象,这就是为什么您会遇到异常。

正如我在your other question的回答中所述,您不能在​​块内分配对象。即使是下面的模式也是一个坏主意,因为那么您将a分配给不同的对象,这意味着下一个要调用​​的线程将在不同的a上这样做,因此2个线程可以同时在相同的​​块中。

synchronized(a){ 
    a.wait(); 
    // still a bad idea 
    a = 55; 
} 
0

在第一种情况,变量a(分配给新的整数后)没有“一”一个已经通过同步的(a)中,因此调用a.wait(锁定)导致异常。