2009-10-12 192 views
28

为什么会发生这种情况?问题是,监测对象是不是null肯定的,但我们仍然可以得到这个异常往往:java.lang.IllegalMonitorStateException:(m = null)无法获取显示器

java.lang.IllegalMonitorStateException: (m=null) Failed to get monitor for (tIdx=60) 
     at java.lang.Object.wait(Object.java:474) 
     at ... 

是挑起这是一个简单的池解决方案的代码:

public Object takeObject() { 
     Object obj = internalTakeObject(); 
     while (obj == null) { 
      try { 
       available.wait(); 
      } catch (InterruptedException e) { 
       throw new RuntimeException(e); 
      } 
      obj = internalTakeObject(); 
     } 
     return obj; 
    } 

    private Object internalTakeObject() { 
     Object obj = null; 
     synchronized (available) { 
      if (available.size() > 0) { 
       obj = available.keySet().iterator().next(); 
       available.remove(obj); 
       synchronized (taken) { 
        taken.put(obj, Boolean.valueOf(true)); 
       } 
      } 
     } 
     return obj; 
    } 

    public void returnObject(Object obj) { 
     synchronized (taken) { 
      taken.remove(obj); 
     } 
     synchronized (available) { 
      if (available.size() < size) { 
       available.put(obj, Boolean.valueOf(true)); 
       available.notify(); 
      } 
     } 
    } 

我缺少的东西?

编辑:异常发生在available.wait();行。

+0

你能告诉我们源代码中的474行是什么吗? – flybywire 2009-10-12 10:52:54

+0

异常发生在available.wait();行,但第474行来自java.lang.Object类。 – 2009-10-12 10:55:59

回答

53

查看的Object.wait的Javadoc。

尤其是“当前线程必须拥有该对象的显示器。”和“[throws] IllegalMonitorStateException - 如果当前线程不是对象监视器的所有者。”也就是说,您需要在要调用的对象上同步等待。

所以你的代码应该是:

synchronized (available) { 
    available.wait(); 
} 
+3

值得一提:如果'available.notify()'发生这种异常,请使用相同的模式。 – 2012-12-11 11:57:11

+0

我尝试使用同步函数而不是块来做同样的事情,但它抛出IllegalMonitorStateException。这是为什么? – 2016-01-07 00:32:27

+0

亨特,当你使一个成员函数同步时,你正在锁定对象 - 所以'this.wait()'应该工作。你究竟做了什么? – tgdavies 2016-01-07 11:02:39

6

available.wait();必须以同步的(可用的)部分

0

takeObject()方法必须是同步的,或者我们写这个方法里面synchronized块。我希望你应该为此编译时间异常。