2009-10-12 7 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(); 
      } 
     } 
    } 

私が何かをしないのです?

EDIT:例外はavailable.wait();行で発生します。

+0

ソースコードで474行目を教えてください。 – flybywire

+0

例外はavailable.wait()で発生します。行474はjava.lang.Objectクラスからのものです。 –

答えて

53

はObject.waitのjavadocを参照してくださいでなければなりません。

特に "現在のスレッドはこのオブジェクトのモニタを所有している必要があります。"および "[throws] IllegalMonitorStateException - 現在のスレッドがオブジェクトのモニタの所有者でない場合つまり、待機するオブジェクトを同期させる必要があります。

ので、あなたのコードは次のようになります。

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

知っておく価値がある:この例外が 'available.notify()'で発生した場合、同じパターンを使用してください。 –

+0

同じことをするためにブロックの代わりに同期関数を使用しようとしましたが、IllegalMonitorStateExceptionがスローされました。何故ですか? –

+0

ハンター、メンバーの機能を同期させると、オブジェクトをロックしているので、 'this.wait()'は動作するはずです。あなたは何をしましたか? – tgdavies

6

available.wait();は同期(利用可能)セクション

0

takeObject()メソッドは、私たちは、このメソッドの内部同期ブロックを記述する必要があり、同期またはしなければなりません。私はあなたがこれのためにコンパイル時の例外を取得する必要があります。

関連する問題