java.lang.IllegalMonitorStateException等待并通知

时间:2014-05-13 15:46:07

标签: java multithreading

我正在尝试使用wait和notify来暂停线程,直到调用某个方法。我目前设置如下:

On thread有一个方法:

    public void toggleTurnOver(){
    if(turnOver == false){
        turnOver = true;
        synchronized(this){
            for(Player p: playerList){
                p.notify();
            }
        }
    }else{
        turnOver = false;
    }
}

这个方法将唤醒此线程中的其他等待:

                        synchronized(myGame){
                        if(!myGame.getTurnOver()){
                            try {
                                wait();
                            } catch (InterruptedException e) {
                                // TODO Auto-generated catch block
                                e.printStackTrace();
                            }
                            pr.println(myGame.getTurnOver());
                            pr.flush();
                        }
                    }

它们在同一个对象上同步,因此不确定是什么原因导致抛出该异常。有什么想法吗?

抛出的确切错误是:

Exception in thread "Thread-3" Exception in thread "Thread-2" java.lang.IllegalMonitorStateException
    at java.lang.Object.wait(Native Method)
    at java.lang.Object.wait(Object.java:503)
    at Player.run(Player.java:112)
java.lang.IllegalMonitorStateException
    at java.lang.Object.notify(Native Method)
    at Game.toggleTurnOver(Game.java:764)
    at Game.run(Game.java:386)

2 个答案:

答案 0 :(得分:4)

documentation中的第一句话:

  

抛出指示线程已尝试在对象的监视器上等待或通知在对象的监视器上等待的其他线程,而不拥有指定的监视器。

您正在通过p通知,因此您必须在p上进行同步:

for(Player p: playerList) {
  synchronized(p){
    p.notify();
  }
}

等待时也一样:你必须同步你正在等待的对象(假设这段代码在Player类中):

if(!myGame.getTurnOver()){
    try {
        synchronized(this){
            wait();
        }
    } catch (InterruptedException e) {
        // ...
    }
}

答案 1 :(得分:0)

在互联网上引用我最喜欢的page

  

让线程t成为对象m上执行wait方法的线程,并且让n为t上的t锁定动作的数量,这些动作与解锁动作没有匹配。发生以下行为之一:
    - 如果n为零(即,线程t尚未拥有目标m的锁),则抛出IllegalMonitorStateException。
    - 等等等等等等

这意味着,您不仅必须在调用notify时在同一对象上进行同步,还必须与您正在等待并通知的对象相同。在这种情况下,您正在myGame进行同步,但正在等待并通知Player