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

时间:2011-02-17 21:51:41

标签: c# asp.net deadlock

为什么这段代码不会造成死锁?

   private static readonly object a = new object();

...

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

3 个答案:

答案 0 :(得分:42)

如果一个线程已经拥有一个锁,那么它可以再次“取消锁定”。


至于为什么,(以及为什么这是一个好主意),请考虑以下情况,其中我们在 - >程序的其他地方有一个已定义的锁定顺序。 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()时,我们的锁定顺序会保持不会发生自我死锁。

答案 1 :(得分:18)

lock关键字使用可重入锁定,这意味着当前线程已经锁定,因此它不会尝试重新获取它。

如果

,就会发生死锁

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

两个线程现在都在等待,因此陷入僵局。

答案 2 :(得分:8)

来自C#语言规范的section 8.12

  

虽然举行互斥锁定,   代码在同一执行中执行   线程也可以获取和释放   锁。但是,代码在其他代码中执行   线程被阻止获取   锁定直到锁定被释放。

很明显,内部lock范围与外部{{p}>在同一个线程中。