如果我们在没有synchronized
块的对象上调用wait()
、notify()
或notifyAll()
,我们会在运行时得到一个IllegalMonitorStateException
。
如果我尝试在没有同步块的情况下调用这些方法,为什么编译器不标记我?
调用这些方法只需要当前线程是对象监视器的所有者。但是,这可能意味着从另一个同步块的上下文中调用一个没有同步的方法。
例如:
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);
}
通常,现在有办法在编译时知道当当前线程没有特定监视器时是否会执行任何代码段,这可能是编译器甚至不尝试标记它的原因。
无法证明堆栈中更高级的方法尚未获得监视器。
例如:
class Foo
{
void foo()
{
synchronized (bar)
{
bar.bar();
}
}
}
class Bar
{
void bar()
{
this.wait();
}
}
将是合法的(假设bar
是Bar
的实例),但不可能证明没有代码可以在不首先获得监视器的情况下调用bar
。
由于从一个线程到另一个线程的执行总是在运行时发生变化,并且您可以遇到生产者-消费者问题,因此无法在编译时模拟问题,因为消费者正在使用缓冲区,一旦缓冲区被消耗,它就会在那时通知生产者,直到那时生产者将等待,否则会出现异常,所以这些方法的整个逻辑都在同步块中