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

Mys*_*ter 49 c# asp.net deadlock

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

   private static readonly object a = new object();
Run Code Online (Sandbox Code Playgroud)

...

   lock(a)
   {
      lock(a)
      {
         ....
      }
   }
Run Code Online (Sandbox Code Playgroud)

Ano*_*on. 44

如果一个线程已经拥有一个锁,那么它可以再次"取消锁定"而不会出现问题.


至于为什么会这样,(以及为什么这是一个好主意),请考虑以下情况,其中我们在 - > 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
    }
}
Run Code Online (Sandbox Code Playgroud)

糟糕,我们只是违反了我们的锁定顺序,并且可能会陷入僵局.

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

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
    }
}
Run Code Online (Sandbox Code Playgroud)

这样我们的锁定顺序就可以保持,当我们打电话时没有自我死锁f().


Dav*_*vy8 18

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

如果发生死锁

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

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


Dan*_*n J 8

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

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

很明显,内部lock范围与外部范围在同一个线程中.