2011-02-17 138 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范围与外部线程在同一个线程中。