为什么嵌套锁不会导致死锁?

可能重复:
C#中的重入锁

为什么这个代码不会导致死锁?

private static readonly object a = new object(); 

  lock(a) { lock(a) { .... } } 

如果一个线程已经拥有一个锁,那么它可以“再次获得该锁”而没有问题。


至于这是为什么 ,(为什么这是一个好主意),考虑下面的情况,我们有一个定义的locking顺序在其他程序中 – > 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 } } 

哎呀,我们刚刚违反了我们的locking顺序,并在我们手中有潜在的僵局。

我们真的需要能够做到以下几点:

 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 } } 

这样我们的locking顺序就被维护了,当我们调用f()时候没有自我死锁。

lock关键字使用重入锁,这意味着当前线程已经拥有该锁,所以它不会尝试重新获取它。

如果发生死锁

线程1获取lockingA
线程2获取lockingB
线程1尝试获取锁B(等待线程2完成)线程2尝试获取锁A(等待线程1完成)

两个线程现在正在彼此等待,从而陷入僵局。

从C#语言规范的第8.12节 :

在保持互斥锁的同时,在同一个执行线程中执行的代码也可以获得并释放该锁。 但是,在locking被释放之前,在其他线程中执行的代码被阻止获取locking。

内部的lock范围应该与外部在同一个线程中。