2015-09-20 42 views
-1

假設有一個人試圖將20美元從銀行賬戶A轉移到銀行賬戶B,另一個人試圖同時從銀行賬戶B轉移30美元到銀行賬戶A.爲什麼這應該導致僵局?不能每個線程執行以下操作:爲什麼發生死鎖?難道你不能在程序中釋放鎖嗎?

線程1 獲取的鎖 從A 版本A的鎖 採集B的鎖撤櫃$ 20 添加$ 20到B 版本B的鎖

線程2 採集B的鎖定 的B 版本B的鎖 獲取的鎖撤櫃$ 30 添加$ 30所述的 版本A的鎖

我知道如果資源在每個線程結束時被釋放,會造成死鎖。然而,爲什麼一個線程只要完成資源就簡單地釋放一個資源的鎖?

回答

2

假設有一個人試圖從銀行賬戶A轉賬20美元到銀行賬戶B,另一個人試圖同時從銀行賬戶B轉賬30美元到銀行賬戶A.爲什麼這應該導致僵局?

它不會。這不是真正的銀行業務的工作原理。

你大概是從某種類比或簡化的版本推理來演示這個概念。

線程1獲取的鎖從A版本A的鎖獲取B的鎖撤櫃$ 18添加$ 20到B版本B的鎖

像這樣的事情很可能確實是真實的代碼來完成。

需要注意的是,如果由於某種原因我們無法獲得鎖B,我們需要再次獲得鎖A才能返回20美元,因爲如果我們在失敗的情況下無法返回20美元,我們不會沒有一筆交易要麼完全成功,要麼完全失敗,20美元可能會消失。因此,如果在未能獲得鎖B之後,我們可能無法再獲得鎖A,這是不可接受的。如果某種東西可能會獲得A和B的鎖,並根據它們所保護的值作出決定,這也是不可接受的;他們的總和在這一點上是不正確的。

另一種可能的方法是訂購鎖。如果A總是出現在B之前,那麼無論它們以何種方式轉移資金,兩個線程總是會試圖在鎖B之前獲得鎖A,並且永遠不會發生死鎖。一個重要的警告是,如果你有鎖B並意識到你也需要鎖A,那麼你必須在獲得鎖A之前釋放鎖B.

另一種可能的方法是在死鎖時一個事務丟失,其工作撤消並且其鎖釋放也許在重試之前,或者可能有例外(或者在例外之前可能有一定次數的重試)。這在數據庫鎖定中很常見。請注意,這需要一些控制代碼來注意已完成的工作,以便它可以撤消。交易事務數據庫就是這樣,但絕大多數多線程程序都是如此。

0

死鎖發生時,說2資源互相等待釋放資源。想想你正在穿過一條狹窄的街道,只有一個人可以立即通過,突然間你會面對另一個來自相反方向的人。現在你們都會等待對方釋放資源(這是街道),到那時你們將陷入僵局。

這是第一人必須將資金從賬戶A轉移到B,他必須獲得兩個賬戶才能執行從A點到B點的交易,賬戶持有人1正在等待賬戶B獲得釋放,但賬戶持有人2正在等待賬戶A被釋放,如果你能想象,這會形成一個無限循環的等待狀態(或死鎖)。

現在考慮你上面提出的建議,線程1不能釋放A的鎖定,除非事務完成。如果這種情況發生,如你所說!如果在獲得20美元后,線程A的鎖被釋放並扣除20美元,並且由於任何異常,賬戶B的交易失敗,現在交易將不得不回滾,假設賬戶A正被其他線程佔用!你能否看到這可能導致無限期的等待以及數據不一致的進一步例外。假設用戶向B發送20美元,並在此後立即停用其賬戶,並且如果交易失敗,資金將轉到何處?

可能的解決方案,以給定的情景(死鎖後已發生):

  1. 不會相互排斥,(意味着沒有鎖定,沒有什麼好你知道更好,如果你離開會發生什麼你資源(比如肉)給飢餓的狗(線程)。你的系統會去的狗最終(開玩笑的,簡單地說:這是不可能不遵循相互排斥的原理)

  2. 允許搶佔 •OS可以從當前所有者

  3. 沒有保持吊銷資源等待 •當等待資源,不得目前持有的任何資源

  4. 請求的資源,以便 •在等待資源「X」,當前不得持有任何資源「Y」•正如你可以看到:如果你的程序滿足了#3,那麼它滿足#4

1

下面是我對這個觀點。

這是1個線程的步驟,以轉移資金:

  1. 採集鎖A.
  2. 從A撤櫃$ 20
  3. 採集鎖B.
  4. 添加$ 20至B.
  5. 釋放鎖B.
  6. 釋放鎖A.

那麼,爲什麼不從A提取20美元后釋放鎖A? 轉賬必須是交易。這意味着在完成上述6個步驟之後,它才被標記爲成功。如果出現問題,它必須回滾一切。

讓我們想象一下,在步驟4中,由於某種原因,Add $20 to B失敗。這使得線程回滾,add $20 back to A。那時候,如果lock A被其他線程佔用,它將導致無限期的等待和一些進一步的問題。

這就是爲什麼它必須持有鎖A直到交易完成。