首先,如果在未持有对象锁的情况下调用object.wait()/notify(),直接会报错,JDK已经做好保护。
其次,为什么要这么设计?其实这是一种安全设计,为了防止wait错过notify。请看下面代码:
boolean wakeuped = false;
void dowait()
{
if(wakeuped)
return;
wait();
}
void wakeup()
{
wakeuped = true;
notify();
}
如果一个线程 执行dowait,另一个线程执行wakeup,在没有同步保护的情况下可能存在着这样的执行循序:
[wait thread ] if(wakeuped) return;//wakeuped is false;
[notify thread] wakeuped=true;// wakeuped is true
[notify thread] notify();//此时wait线程没有进入wait,
[wait thread ] wait();//wakuped is true,此时进入wait,而notify先于wait执行,此时wait将不会被唤醒。
在dowait和wakeup两个方法上加上同步锁保护,则可以保证不会出现上面的执行顺序。wakeup要么先于dowait执行,要么在dowait线程进入wait后才能执行。这样通过互斥锁来保证wait()/notify()之间的先后顺序,才能保证wait不会错过notify,从而导致wait线程一直挂着。