java.lang.IllegalMonitorStateException 等待并通知

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/23635857/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-14 00:26:48  来源:igfitidea点击:

java.lang.IllegalMonitorStateException wait and notify

javamultithreading

提问by awmusic12635

I am trying to use wait and notify to halt threads until a certain method is called. I currently have it setup as the following:

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

On thread has a method with:

在线程上有一个方法:

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

This method will be what is waking up the other wait that is located in this thread:

此方法将唤醒位于此线程中的另一个等待:

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

They are synchronized on the same object so am not sure what would be causing that exception to be thrown. Any ideas?

它们在同一个对象上同步,所以我不确定是什么导致抛出异常。有任何想法吗?

Exact error thrown is:

抛出的确切错误是:

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)

回答by king_nak

First sentence in the documentation:

文档中的第一句话:

Thrown to indicate that a thread has attempted to wait on an object's monitor or to notify other threads waiting on an object's monitor without owning the specified monitor.

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

You are notifying on p, so you have to synchronize on p:

您正在通知p,因此您必须同步p

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

Same thing when waiting: you have to synchronize on the object you're waiting (assuming this code is in Playerclass):

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

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

回答by Ordous

Quoting my favorite pagein the internet:

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

Let thread t be the thread executing the wait method on object m, and let n be the number of lock actions by t on m that have not been matched by unlock actions. One of the following actions occurs:
- If n is zero (i.e., thread t does not already possess the lock for target m), then an IllegalMonitorStateException is thrown.
- blah blah blah

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

As this implies, you not only have to be synchronized on the same object when calling notify, it also has to be the same object that you are waiting and notifying on. In this case you are synchronizing on myGame, but are waiting and notifying on Player

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