2010-10-19 74 views
3

我有Java中的舊代碼,它會死鎖...我從來沒有使用netbeans作爲開發工具...但是,我需要修復代碼。如何使用NetBeans刪除Java代碼中的死鎖

我在調試模式下運行應用程序,點擊檢查死鎖,netBeans帶來了一個屏幕。四個線程中的兩個線程處於紅色狀態......請參閱下面的屏幕轉儲。

我新的多線程,並在該代碼的頂部是不是我的......

什麼是最有可能造成問題的原因?

alt text

回答

5

至於我可以告訴這個問題很可能與中(或者更具體的順序)的多個線程獲取和釋放鎖的方式。 在上述例子中的兩個線程需要訪問兩個鎖(或監視器):

  • nano.toolbox.strategies.ESMarketMaker
  • nano.toolbox.strategies.ExecutionManager

從堆跟蹤當前處於死鎖狀態的兩個線程,我們可以看到線程'ExecutionManager'獲得了ExecutionManager監視器,但正在等待'ESMarketMaker'監視器正在等待獲取(同時仍持有'ExecutionManager'監視器)。

另一方面,'StrategyManager'線程已經獲得'ESMarketMaker'監視器,但正在等待'ExecutionManager'監視器的獲取(同時仍持有'ESMarketMaker'監視器)。

這是一個死鎖的類示例,以及獲取鎖的順序會導致死鎖的很多方法。

有解決這些類型的問題很多:

  • 如果可能的話,所有的線程需要一些船閘運行的,必須獲得以相同的順序共享鎖(相逆的順序問題在上述僵局中)。但是這並非總是可行的,因爲多個線程在不同條件下可能只有半重疊的鎖使用,爲什麼設計可以確保均勻排序的採集協議可能很難或不可能。
  • 您也可以使用tryLock()來代替它,這是一個非阻塞式獲取,它會返回一個標誌來指示成功或失敗,並讓您在重新嘗試之前執行其他操作。在這種情況下,我會推薦的一件事是,如果獲取失敗,它將放棄所有當前擁有的鎖,並再次從頭開始嘗試(因此讓位於當前線程保留的任何或所有鎖上的任何人完成其鎖定工作,也許可以釋放這個線程在重試時需要的鎖)。

但有一點需要注意的是,有時候在決定使用協議時,需要更多地顯式控制您的鎖,而不是使用Java中的常規同步。在這些情況下,顯式ReentrantLock實例的使用可以是一個好處,因爲它們允許您執行諸如檢查鎖是否已解鎖或當前已鎖定等操作,並執行上述非阻塞try-lock。

我希望這可以幫助,我很抱歉,我不能更具體,但我需要看到源代碼。:-)

(哦,ps,人們可能會選擇的第三件事,如果死鎖是所有成本都必須避免的事情,那就是研究建模工具,在程序狀態上建模一個狀態機和鎖,它們可以與分析工具一起使用,分析工具可以檢查這種模型中可能存在的死鎖並給出示例,如果發現任何這樣的情況)。

+2

+1 ...但我不同意釋放鎖和重新獲取它們的部分。如果兩個代理做同樣的事情,那麼他們可能會遇到一個活鎖。基本上,兩個代理不斷獲得第一個鎖,未能獲得第二個鎖,釋放第一個鎖,並連續重複該過程。 – 2010-10-19 23:21:04

+0

這當然是對的,這樣的條件在理論上是可行的,因此應該謹慎使用解決方案,因爲它不是防彈的。儘管如此,我認爲這樣的調度(在現實生活中)不大可能不說不存在,因爲它需要無限期地一致地調度「錯誤」的交錯。有人可能稱之爲「解決方案」樂觀,因爲它依賴於調度器的僞隨機行爲來確保(在無限期的時間內)在某個點嘗試「正確」交織。 – micdah 2010-10-19 23:35:37

+0

也許一個更好的解決方案,假設人們事先知道準確執行操作所需的鎖,就是試圖在每次重試時以僞隨機順序獲取這些鎖,直到獲得所有鎖,這種隨機性與非阻塞獲取相結合肯定會(給定無限期)確保線程在某個時刻可以獲得所有需要的鎖。 – micdah 2010-10-19 23:39:17