2009-09-19 196 views
5

我在.net/C#中被問及這個問題:交易 - 如何避免死鎖?

如果我們有兩個線程T1和T2。 T1 獲取obj1上的鎖定,然後執行 某些處理並獲取 obj2上的鎖定。 T2獲得對obj2的鎖定並且 然後進行一些處理並獲取 對obj1的鎖定。所以,我們可以有一個 死鎖。我們在多線程中使用的常見技術 是什麼,以避免 這種情況?

我回答說T1和T2應該有一定的溝通機制,我們應該這樣編碼,使得T2只有在T1發出信號後纔開始工作。面試官問我是否知道交易以及如何使用它來解決這種僵局。 我在winforms的UI方面有一定的多線程經驗。但是,我從來沒有使用過交易。有人可以告訴我更多關於此的信息,或者將我指向url/book,

回答

7

避免死鎖的一種常規方法是確保您的線程/進程以相同的順序獲取資源上的鎖。例如,T2應該首先鎖定obj1,然後obj2(與T1相同)。

這樣你就不能讓兩個線程持有另一個線程想要的資源,即死鎖。

如果您的報價中的措詞是確切的問題,那麼寫得很糟糕。它應該是:

T1獲取鎖OBJ1,確實 東西,然後試圖鎖定也 obj2的未解鎖OBJ1。 同時 T2獲取 對obj2的鎖定,做一些事情,然後 然後試圖在沒有解鎖obj2的情況下鎖定obj1。 A會發生死鎖。

我強烈推薦閱讀Joe Duffy的Concurrent Programming on Windows。這可能是關於Windows線程理論和實踐的最全面的書。

+0

@Ash我得到了以相同的順序獲取鎖定點。但是,那麼關於交易的是什麼呢? – Sandbox 2009-09-19 10:32:17

+1

@Sandbox,對我來說,他們看起來像是在談論一個「事務」,一般意義上說是確保一系列不同的操作是作爲一個(即原子)執行的。在數據庫中,這是通過Begin Transaction關鍵字在.net中實現的,它通過(通常)使用lock語句來實現。我在答覆中添加了Joe Duffy強烈推薦的書。 – Ash 2009-09-19 10:56:58

3

一種方法是所有進程都需要在事務開始時獲取所有鎖。如果某些不可用,該進程將釋放所有鎖,然後重試。根據實施情況,這仍然可能導致活鎖。

要從另一端看問題,請參閱Dijkstra's banker's algorithm

1

我並不完全確定交易到哪裏直接進去了,除了回滾的能力。國際海事組織的主要目的是以一致的順序獲得鎖具,並提前;哦,並在獲取鎖定時使用超時 - 不要坐在那裏看起來永遠卡住。

的交易參考讓我首先想到的數據庫,在這種情況下,另一個考慮是使用的技巧,比如UPDLOCK,以確保你得到一個寫鎖最初以避免促進(有爭議)讀鎖問題寫-lock(從死鎖變爲簡單的阻塞)。當然,許多數據庫也比大多數常規代碼具有更好的死鎖檢測。

+0

我認爲術語「事務」通常意味着確保多個非原子操作按原子執行。通常的解決方案是使用鎖定。 – Zed 2009-09-19 07:15:53

1

我認爲面試官所指的是回滾事務的能力。事務的回滾將恢復事務所做的所有更改,就好像事務從未發生過一樣。它也將釋放它獲得的所有鎖。

現在讓示例中的每個線程使用自己的事務(在數據庫,Vista文件系統或支持事務的其他接口中)。如果發生死鎖(一旦發生死鎖就可以輕鬆檢測到),您將從線程中選擇一個死鎖(受害者)的一部分並回滾其事務。這將釋放鎖,以便剩下的線程可以繼續。受害者線程可能會重試該事務。

如果死鎖的概率低於重試整個事務的成本,這可能是可用的解決方案。