在哪里叫wait()

时间:2012-03-06 04:31:10

标签: java multithreading

在我的java程序中,当我编码

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

它在java.lang.IllegalMonitorStateException语句中提供运行时异常a.wait();。但是a=55成功运行。

但如果我编码为

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

然后它完美运行,没有任何异常。为什么呢?

3 个答案:

答案 0 :(得分:3)

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

换句话说,有两个对象val1val2都分配给变量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()会导致异常。