2011-12-05 11 views
1

私たちの以前の開発者の一人によって書かれたAndroidのサービスをデバッグしていて、彼は次のようにBooleanを使用しています:synchronized(lock){lock.notify();} ...でスローされたIllegalMonitorStateExceptionなぜですか?

public static class DownloadQueue extends LinkedHashMap 
{ 
    // ... 
    private Boolean lock = new Boolean(false); 
    // ... 

    //typical notify use 
    synchronized public Object addToHead(Object key, Object value) 
    { 
     // ... 
     synchronized (lock) 
     { 
      //IllegalMonitorStateException FROM HERE 
      lock.notify(); 
     } 
     // ... 
     return null; 
    } 

    //queue machinery 
    public DownloadRecord getFirst() 
    { 
     // we block because queue is empty 
     if(this.size() == 0 || (MyApp.isInternetConnectionAvailable() == false)) 
     { 
      try 
      { 
       lock = true; 
       synchronized (lock) 
       { 
        lock.wait(30000); 
       } 
       lock = false; 
      } 
      catch (InterruptedException e) 
      {} 
     //continue operating the queue 
     // ... 
     return value; 
    } 
} 

私はIllegalMonitorStateExceptionで見つけた文書は、それがからnotify()を呼び出していないことが原因で発生だことを示唆していますブロック​​;しかし、それは明らかにここでは当てはまりません。 lockのスコープが問題であるかどうか、または同期されていない割り当てが可能かどうかは疑問でした。 lockへのすべての参照は、上記の形式であり、キュー機能にあるのはwait(long)です。

最終的な、おそらく有用な詳細:私たちのデバイスはネットワークを持っていますが、私たちのCMSはダウンしています。この状態でアプリをテストする機会があります。失敗したダウンロードがキューに入れられているため、競合状態がこのフォルトの原因である場合は、原因が原因である可能性があります。

ありがとうございます!

答えて

4

お客様のgetFirstメソッドで、メンバー変数lockの値を再割り当てすることが問題です。

ブール値は不変型です。その値を再割り当てすると、新しいオブジェクトが作成されます。

これは、同期した同じオブジェクトに通知することが保証されていないことを意味します(その間に再割り当てが行われた場合)。

この種のプログラミングエラーを避けるために、ロック変数をfinalと宣言することをお勧めします。

+0

ありがとうございました!それは私の解決策に似ています:) –

+0

さらに、 'lock'の値が決して読み込まれないと判断したので、書き込みを取り除きました。 –

4

ロック変数のシンクロナイゼーションは、再割り当てを続けるため、機能しません。これを行うときは、lock = true;またはlock = false;は、「ロック」が参照するオブジェクトを変更しています。したがって、addToHeadメソッドでロックを取得し、別のスレッドがgetFirstを呼び出すと、ロックの参照がその下で変更され、通知する時間までに何か別のものを指すようになります。

+0

ありがとうございました。上記のように –

関連する問題