2009-02-09 145 views
39

死鎖很難找到,非常不舒服。什麼是死鎖的常見原因?

如何在我的代碼中找到死鎖的錯誤源?有沒有「僵局模式」?

在我的特殊情況下,它處理數據庫,但是這個問題對每個死鎖都是開放的。

+1

注:它的「僵局」而不是「死鎖」。一個詞。 – 2009-02-09 14:30:37

+0

你是在談論數據庫死鎖或者有關C#/ Java等的死鎖嗎? – SQLMenace 2009-02-09 14:23:00

回答

28

更新:此最近的MSDN文章,Tools And Techniques to Identify Concurrency Issues,也可能會感興趣


斯蒂芬Toub MSDN文章Deadlock monitor各國需要以下四個條件發生死鎖:

  • 數量有限的特定資源。對於C#中的監視器(使用lock關鍵字時使用的內容),由於監視器是互斥鎖(意味着一次只能有一個線程可以擁有監視器),因此此限制數爲1。

  • 能夠保存一個資源並請求另一個資源。在C#,這類似於鎖定一個物體上,然後釋放第一鎖,例如之前鎖定在另一:


lock(a) 
{ 
... 
    lock(b) 
    { 
      ... 
    } 
} 
  • 沒有搶佔能力。在C#中,這意味着一個線程不能強制另一個線程釋放鎖。

  • 循環等待條件。這意味着有一個線程循環,每個線程都在等待下一個線程釋放資源,然後才能繼續。

他繼續解釋說,避免死鎖的方法是避免(或阻止)條件四。

Joe Duffy discusses several techniques 用於避免並檢測死鎖, 包括一個被稱爲鎖找平。 在鎖定級別中,鎖被指定爲 數值,並且線程必須獲取的鎖具有比其已獲取的鎖具有更高的 數字的鎖。這可以防止循環的可能性。這也是 在 今天典型的軟件應用, 和一個失敗鎖定水平 每個鎖採購邀請 死鎖通常很難做好。

1

典型的情況是不匹配的更新計劃(表不總是按照相同的順序更新)。然而,在高處理量下,發生死鎖並不罕見。

我傾向於接受死鎖作爲生活中的事實,它會在某一天發生,所以我讓我的DAL準備處理並重試死鎖操作。

4

是 - 進程嘗試以隨機順序獲取資源時發生死鎖。如果您的所有進程都嘗試以相同的順序獲取相同的資源,那麼死鎖的可能性會大大降低,如果不能消除的話。

當然,這並不總是容易安排......

12

經典的僵局的情況是一個持有鎖X和想要獲取鎖Y,而B是持有鎖Y和想要獲取鎖X 。既然兩者都不能完成他們正在嘗試做的事情,最終會永遠等待(除非使用超時)。

在這種情況下,如果A和B以相同順序獲取鎖,可以避免死鎖。

8

確保所有事務以相同順序影響表是避免最常見死鎖的關鍵。

例如:

事務A

UPDATE Table A SET Foo = 'Bar' 
UPDATE Table B SET Bar = 'Foo' 

事務B

UPDATE Table B SET Bar = 'Foo' 
UPDATE Table A SET Foo = 'Bar' 

這是極有可能導致死鎖作爲事務A取得鎖定在表A上,事務處理B在表B上獲得鎖定,因此它們都不會爲其第二個命令獲得鎖定,直到另一個完成。

所有其他形式的死鎖通常是由於高強度的使用和SQL Server在內部分配資源時發生死鎖而引起的。

8

據我所知沒有任何死鎖模式(以及1​​2年的大量多線程交易應用程序)。但是TimedLock類對尋找存在於代碼中的死鎖沒有大量返工有很大的幫助。

http://www.randomtree.org/eric/techblog/archives/2004/10/multithreading_is_hard.html

基本上,(在DOTNET/C#),你查找/替換所有的 「鎖(XXX)」 語句以 「使用TimedLock.Lock(XXX)」

如果死鎖檢測過(無法在指定的超時時間內獲得鎖定,默認爲10秒),則拋出異常。我的本地版本也立即記錄堆棧跟蹤。走上堆棧跟蹤(最好使用行號進行調試構建),您將立即看到在失敗點保存了哪些鎖,以及它試圖獲取哪個鎖。

在dotnet 1.1中,在所描述的死鎖情況下,幸運的是所有被鎖定的線程都會在同一時間拋出異常。所以你會得到2+棧跟蹤和解決問題所需的所有信息。 (2。0+可能已經改變的線程模型內部夠不得到這樣的運氣,我不知道)

1

(根據我的觀察不科學)DB死鎖情況非常簡單,最常見的:

  • 兩進程讀取數據(例如數據庫記錄),都獲取相關資源上的共享鎖(通常是數據庫頁面),
  • 兩者都嘗試進行更新,嘗試將其鎖升級爲獨佔鎖 - 瞧,死鎖。

如果讀取後面跟有更新,則可以通過指定「FOR UPDATE」子句(或類似的,取決於特定的RDBMS)來避免這種情況。通過這種方式,流程從一開始就獲得排它鎖定,使上述情況變得不可能。

2

我推薦閱讀Herb Sutter這篇文章。它解釋了死鎖問題背後的原因,並提出瞭解決這個問題的框架this article

1

出現兩個進程每個都等待其他進程完成的情況之前,結果都是程序掛起。其最多的多任務和clint /服務器。

0

死鎖主要發生在存在多個從屬鎖的情況下。在一個線程中,另一個線程試圖以相反的順序鎖定互斥體。應該注意使用互斥鎖來避免死鎖。

解鎖後務必完成操作。如果您有多個鎖,例如訪問訂單是ABC,則發佈訂單也應該是ABC。

0

在我上一個項目中,我遇到了SQL Server數據庫中的死鎖問題。找到原因的問題是,我的軟件和第三方軟件正在使用相同的數據庫並且正在使用相同的表格。很難找出導致僵局的原因。我最終編寫了一個sql查詢來找出哪些進程導致了哪些sql語句導致了死鎖。你可以在這裏找到這樣的語句:Deadlocks on SQL-Server

相關問題