2011-02-17 135 views
38

可能重複:
Re-entrant locks in C#爲什麼嵌套鎖不會導致死鎖?

爲什麼這個代碼不會導致死鎖?

private static readonly object a = new object(); 

...

lock(a) 
    { 
     lock(a) 
     { 
     .... 
     } 
    } 
+0

你爲什麼期望它導致死鎖? (另外,這與http://stackoverflow.com/questions/391913/re-entrant-locks-in-c可能有所幫助) – AakashM 2011-02-17 21:53:17

+3

這顯然是重複的,但這個問題的標題是無限更好的(對於那些可能會尋求它的人)。 – 2011-02-17 21:57:04

回答

34

如果一個線程已經擁有一個鎖,那麼它可以「再次獲得該鎖」而沒有問題。


至於爲什麼即,(爲什麼這是一個好主意),考慮以下情況,我們有一個定義鎖在一個程序中其他地方訂購 - > B:

void f() 
{ 
    lock(a) 
    { /* do stuff inside a */ } 
} 

void doStuff() 
{ 
    lock(b) 
    { 
     //do stuff inside b, that involves leaving b in an inconsistent state 
     f(); 
     //do more stuff inside b so that its consistent again 
    } 
} 

哎呀,我們剛剛違反了我們的鎖定順序,並且在我們手中有潛在的僵局。

我們真的必須能夠做到以下幾點:

function doStuff() 
{ 
    lock(a) 
    lock(b) 
    { 
     //do stuff inside b, that involves leaving b in an inconsistent state 
     f(); 
     //do more stuff inside b so that its consistent again 
    } 
} 

所以我們鎖定順序保持不變,沒有自我鎖死,當我們調用f()

18

lock關鍵字使用重入鎖,這意味着當前線程已經鎖定,因此不會嘗試重新獲得它。

發生死鎖如果

線程1所獲取鎖A
線程2所獲取鎖乙
線程1名試圖獲取鎖B(對線程2等待用它做) 線程2名試圖獲取鎖A(等待線程1完成它)

兩個線程現在正在彼此等待並因此死鎖。

+0

試圖找到一個非重入鎖的例子,但谷歌正在讓我失望。 – Davy8 2011-02-17 22:03:24

8

從C#語言規範的section 8.12

雖然互斥鎖已被佔用, 代碼在同一個執行線程 執行也能獲得和釋放 鎖。但是,其他 線程中執行的代碼被阻止獲取 鎖,直到鎖被釋放。

應該很明顯,內部lock範圍與外部線程在同一個線程中。