2011-12-05 92 views
1

我調試通過我們之前的開發者之一寫一個Android服務,而他使用的Boolean以下列方式:IllegalMonitorStateException拋出synchronized(lock){lock.notify();} ...爲什麼?

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

問題是,您正在重新分配lock成員變量的值在您的getFirst方法中。

布爾是一個不可變的類型,所以當你重新賦值時你正在創建一個新的對象。

這意味着您不能保證通知與您同步的同一對象(如果重新分配發生在兩者之間)。

將鎖變量聲明爲final以避免此類編程錯誤是一種很好的做法。

+0

謝謝!這看起來像我的解決方案:) –

+0

我另外確定'鎖'的值永遠不會被讀取,所以我刪除了寫入。 –

4

您對lock變量的同步化不起作用,因爲您繼續重新分配它:當您執行此操作時lock = true;lock = false;您正在更改「lock」引用的對象。因此,當您在addToHead方法中獲得鎖時,然後另一個線程調用getFirst時,鎖的引用將在其下面更改,以便在您調用notify時指向其他內容。

+0

謝謝,如上:) –

相關問題