2010-01-04 194 views

回答

19

死鎖是併發程序無法繼續執行的情況。

一個線程等待另一個線程 ,而另一個線程 等待第一個線程的 完成。

常用的現實世界的例子是交通流量。

alt text

,沒有流量可以移動到其他的隊列動作。

您可能會對死鎖here找到一個很好的討論。

更新:這是一個java example我在網上找到了(奧雷利書)。它對此有評論,所以你可以很容易地理解它。

Dining Philosophers problem是瞭解死鎖的另一個很好的例子。

去除死ImageShack的鏈接

死鎖檢測和防止死鎖是兩個同時瞭解了死鎖可能有用的相關領域。

+0

我喜歡這個圖。這實際上是我的教授在學習併發時向我展示的,這對我很好。 – 2010-01-04 06:53:25

+0

感謝您提供的鏈接,它非常有幫助。 – Hariharbalaji 2010-01-04 06:58:53

+0

值得注意的是,防止死鎖比查明死鎖機制更重要。在大多數情況下,前者更容易實施。除非你只是殺死僵死的線程:) – jrharshath 2010-01-04 08:34:44

0

死鎖是兩個(或更多)線程每個都在等待另一個完成。線程A不能完成,直到線程B做了一些事情,而線程B不能完成,直到線程A做其他事情。

6

死鎖是當B和B A等待上A.

等待所以,你可以在線程A:

while(B.incomplete()){ 
    B.wait(); 
} A.complete = true; 

,並在線程B:

while(A.incomplete()){ 
    A.wait(); 
} B.complete = true; 
+1

我意識到這是一個很平凡的例子,但你明白了吧? – 2010-01-04 06:51:04

+0

雅謝謝,我明白了。 – Hariharbalaji 2010-01-04 06:58:16

+0

@piggles - 你/你的教授在哪裏得到圖表? – 2013-04-25 09:49:20

1

死鎖是由沒有某種資源控制(例如依賴於兩個資源鎖的圖循環)不能直接解決的資源爭用引起的。

其中最常見的(並且通常用於說明)死鎖情況是鎖反轉:

  • 考慮具有兩個關鍵資源(RESA,RESB),和兩個鎖(洛卡,LOCKB)的應用程序。每個資源都由相應的鎖保護(resA => lockA,resB => lockB)。
  • 兩個資源正在競爭資源,線程A保留lockA(並因此資源A),然後暫停上下文切換),然後才能保留lockB。線程B接收控制權,預留lockB,然後嘗試預留lockA。這導致線程被掛起並且控制權返回給線程A,線程A正在等待lockB,線程B被保持爲線程B.

在這種情況下,由於兩個競爭資源(lockA和lockB)上的兩個線程之間存在循環依賴關係,因此無法單獨干預就無法解決該死鎖。

這可以通過將平凡解決:

  1. 保證了兩把鎖,以便(不是最好的選擇)得到解決
  2. 只有持有每個關鍵部分一把鎖在一個時間(即釋放洛卡在嘗試獲取lockB之前)
+0

+1資源必須是互斥的,否則它們不會被鎖定。 – JCasso 2010-01-04 07:01:08

+0

分辨率1實際上更好。我們假設這些鎖適用於不同的數據結構。如果您一次只持有一個鎖,那麼您不會同時擁有對這兩種數據結構的獨佔訪問權限,並且某些操作無法安全執行。 OTOH,如果你用兩個鎖來替換這兩個鎖,你可以減少併發的範圍;例如對於僅需要兩個原始鎖中的一個的其他操作。 – 2010-01-04 07:35:51

+0

其實我並不是說用一個鎖代替兩個鎖,而只是爲了最佳地一次只擁有一個鎖。有些時候你必須擁有兩把鎖,在這種情況下,#1顯然是首選設計。 – GrayWizardx 2010-01-04 17:00:44

1

下面是一個不使用wait的死鎖示例。只要你有同步,就有可能發生死鎖。

public class Deadlock { 
    static class Deadlocker { 
    private Deadlocker other; 

    public void setOther(Deadlocker other) { 
     this.other = other; 
    } 

    synchronized void doSomethingWithOther() { 
     try { 
     Thread.sleep(1); 
     } catch (InterruptedException e) { 
     } 
     other.doSomething(); 
    } 

    synchronized void doSomething() { 
    } 
    } 

    public static void main(String[] args) { 
    final Deadlocker d1 = new Deadlocker(); 
    final Deadlocker d2 = new Deadlocker(); 
    d1.setOther(d2); 
    d2.setOther(d1); 

    Thread t1 = new Thread() { 
     public void run() { 
     d1.doSomethingWithOther(); 
     } 
    }; 

    Thread t2 = new Thread() { 
     public void run() { 
     d2.doSomethingWithOther(); 
     } 
    }; 

    t1.start(); 
    t2.start(); 
    } 
} 

死鎖當T1處於d1.doSomethingWithOther()(即:對D1的鎖)發生和t2是在d2.doSomethingWithOther()。當每個線程試圖調用對象上的doSomething()時,其他線程都會鎖定,它們最終會卡住,等待彼此。

請注意,死鎖不一定只涉及兩個線程。可以有任意大小的循環。更糟糕的是,一旦獲得了死鎖,任何其他線程也會嘗試依賴死鎖線程,最終本身會死鎖,即使不是循環的一部分。

1

想象下面的邏輯線程。

  1. 在追趕22,小說, 戰鬥機飛行員是由於精神錯亂接地。他可以通過說他沒有瘋狂以便他能夠再次飛行來證明自己的精神錯亂。但通過詢問,想要飛入戰鬥危及他的生命將證明他是瘋了。

  2. 朝鮮希望G7在停止提煉鈾之前提供經濟援助。美國和日本說:「沒有辦法,因爲他們在獲得援助後會反對。」

  3. 系統重啓衝突。

    1. 系統不會關閉,直到 所有用戶進程已經 終止。
    2. 編輯器,用戶進程不會 終止,除非編輯已被保存 。
    3. 編輯無法保存,除非 USB驅動器的存在,因爲 編輯器可執行從 USB驅動器調用。
    4. 由於驅動程序升級 ,USB驅動器被卸除。直到 系統關閉並重新啓動,才能安裝USB驅動器 。
  4. Android機器人具有優越指令

    機器人不得傷害人類,或袖手旁觀,讓一個人來傷害。

    機器人必須遵守人類給予的任何指令,除非這些指令與第一條指令衝突。

    只要保護不與第一或第二指令衝突,機器人就必須保護自己的存在。

該基地的人類住戶發送機器人檢索無線電活動電源。沒有電源,基地就會關閉,人類的殖民地就會死亡。但是機器人發現電源功率非常強大且沒有屏蔽,處理它會導致機器人發生故障並對人類羣體構成威脅。

通過執行阻塞等待, 他們沒有釋放資源 其他線程需要以 疏通每個 對方釋放一些資源,但 等待時
+2

最後一個例子中的+1(0: – 2010-01-04 08:53:53

+1

'你的眼睛裏有蒼蠅,'Yossarian重複道,'這可能是你爲什麼看不到它們的原因'' – 2010-01-04 15:56:17

+0

我們的系統中有文件可能可以因爲存在僵局而看不見? – 2010-01-08 19:20:54

0

線程死鎖。線程無法進行任何 進度,直到資源被髮布,但由於它們不是 正在進行,資源將會從未被釋放, 被鎖定,因此「死鎖」。

Stephen Toub的nice article可能會幫助你一點。