【问题标题】:java.lang.IllegalMonitorStateException wait and notify [duplicate]java.lang.IllegalMonitorStateException 等待并通知[重复]
【发布时间】:2014-07-01 09:34:39
【问题描述】:

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

在线程上有一个方法:

    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)

【问题讨论】:

    标签: java multithreading


    【解决方案1】:

    在网上引用我最喜欢的page

    令线程 t 为对对象 m 执行等待方法的线程,设 n 为 t 对 m 的未与解锁动作匹配的锁定动作的数量。发生以下操作之一:
    - 如果 n 为零(即线程 t 尚未拥有目标 m 的锁),则抛出 IllegalMonitorStateException。
    ——哈哈哈哈哈哈

    正如这所暗示的,在调用 notify 时,您不仅必须在同一个对象上同步,而且它还必须是您正在等待和通知的同一个对象。在这种情况下,您在 myGame 上进行同步,但在 Player 上等待和通知

    【讨论】:

      【解决方案2】:

      documentation中的第一句话:

      抛出表明一个线程试图在一个对象的监视器上等待或通知其他线程在一个对象的监视器上等待而不拥有指定的监视器。

      你在p上通知,所以你必须在p上同步:

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

      等待时也一样:您必须在等待的对象上进行同步(假设此代码在 Player 类中):

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

      【讨论】:

      • 不仅是文档中的第一句,也是唯一不包括继承构造函数的句子
      猜你喜欢
      • 2013-05-29
      • 1970-01-01
      • 1970-01-01
      • 2015-09-13
      • 2018-05-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多