notifyAll()抛出IllegalMonitorStateException

时间:2013-08-13 12:48:23

标签: java multithreading concurrency

我正在设计两个线程:一个必须获取播放器的名称,第二个线程必须等待设置的名称才能继续,但第一个线程中的notify()all抛出了IllegalMonitorStateException错误。

private NameFecth nameFetch;
private UseName useName;
private Object nameSetLock; 
public static void method{
   nameSetLock = new Object()
   nameFetch = new NameFetch(nameSetLock);
   useName = new UseName(nameSetLock);
   Thread nameFetchThread = new Thread(nameFetch);
   nameFetchThread.start();
   Thread useNameThread = new Thread(useName);
   useNameThread.start();
}

public class NameFetch implements Runnable{
    /*variables and constructers*/

    public void run(){
       /*get name and set the variable somehow*/
       synchronized(nameSetLock){
         notifyAll();
       }
    }
}

public class UseName implements Runnable{
    /*variables and constructers*/

   public void run(){
     while(!nameBeenSet){
       synchronized(nameSetLock){
         try{
           wait();
         }catch(InterruptedException e) {}
       }
     }

}

我做错了什么?

4 个答案:

答案 0 :(得分:15)

您正在调用waitnotify,而不会同步您正在等待或通知的内容。如Object.notifyAll中所述:

  

抛出:
  IllegalMonitorStateException - 如果当前线程不是此对象监视器的所有者。

所以这个:

synchronized(nameSetLock){
  notifyAll();
}

应该是:

synchronized(nameSetLock){
  nameSetLock.notifyAll();
}

...同样适用于wait。请注意,您当前的代码甚至无法编译,因为您使用的是syncronized而不是synchronized,这表明您没有发布实际的代码。在键入代码时,您实际上已经更改了问题 - 在这种情况下,您应该编辑您的问题以使其更具代表性。

答案 1 :(得分:1)

看起来你的问题是你正在使用锁。您的同步块是在nameSetLock上,并且您正在NameFetch对象实例上调用您的notifyall(这是一个同步的(这个)。

你应该这样做 当您要使用lock和nameSetLock.notifyAll进行通知时,请设置nameSetLock.wait。

答案 2 :(得分:1)

来自IllegalStateException

的JavaDoc
  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. 

您试图在没有该对象锁定的情况下调用wait()和notifyAll()。

请尝试@Jon建议它会起作用。

答案 3 :(得分:0)

当我忘记在方法调用中添加synchronized时,会发生这种情况。