如果我们在没有wait()
块的对象上调用notify()
,notifyAll()
或synchronized
,我们会在运行时获得IllegalMonitorStateException
。
如果我尝试在没有同步块的情况下调用这些方法,为什么编译器不会标记我?
答案 0 :(得分:7)
调用这些方法只需要当前线程是对象监视器的所有者。但是,这可能意味着在另一个同步块的上下文中调用未同步的方法。
例如:
public void doWait(Object o) {
o.wait(); // you would like the compiler to flag this
}
// but in this case it is valid
synchronized(this)
{
doWait(this);
}
通常,现在有一种方法可以在编译时知道当前线程没有保存特定监视器时是否会执行任何代码,这可能是编译器甚至没有尝试标记这一点的原因。
答案 1 :(得分:1)
无法证明堆栈中的某个方法尚未获得监视器。
例如:
class Foo
{
void foo()
{
synchronized (bar)
{
bar.bar();
}
}
}
class Bar
{
void bar()
{
this.wait();
}
}
合法(假设bar
是Bar
的实例),但无法证明在没有首先获取监视器的情况下没有调用bar
的代码。
答案 2 :(得分:0)
由于从一个线程到另一个线程的执行总是在运行时更改,并且您可以解决生产者 - 消费者问题,因此无法在编译时模拟该问题,因为一旦缓冲区被消耗,消费者正在使用缓冲区,它会通知到那个时候生产者,直到那个时候生产者会等待,否则有异常,所以这些方法的整个逻辑都在同步块内