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

发布于 2024-10-17 16:47:25 字数 203 浏览 4 评论 0原文

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

   private static readonly object a = new object();

...

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

Why does this code not cause a deadlock?

   private static readonly object a = new object();

...

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

浅沫记忆 2024-10-24 16:47:25

如果线程已经持有锁,那么它可以毫无问题地再次“获取该锁”。


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

If a thread already holds a lock, then it can "take that lock" again without issue.


As to why that is, (and why it's a good idea), consider the following situation, where we have a defined lock ordering elsewhere in the program of a -> 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
    }
}

Whoops, we just violated our lock ordering and have a potential deadlock on our hands.

We really need to be able to do the following:

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

So that our lock ordering is maintained, without self-deadlocking when we call f().

从来不烧饼 2024-10-24 16:47:25

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

则会发生死锁

如果线程 1 获取锁 A,
线程 2 获取锁 B
线程 1 尝试获取锁 B(等待线程 2 完成操作)
线程 2 尝试获取锁 A(等待线程 1 完成该操作),

两个线程现在都在互相等待,因此陷入死锁。

The lock keyword uses a re-entrant lock, meaning the current thread already has the lock so it doesn't try to reacquire it.

A deadlock occurs if

Thread 1 acquires lock A
Thread 2 acquires lock B
Thread 1 tries to acquire lock B (waits for Thread 2 to be done with it)
Thread 2 tries to acquire lock A (waits for Thread 1 to be done with it)

Both threads are now waiting on each other and thus deadlocked.

小草泠泠 2024-10-24 16:47:25

来自 C# 语言规范的 第 8.12 节

当持有互斥锁时,
在同一执行中执行的代码
线程还可以获取和释放
锁。但是,在其他中执行的代码
线程被阻止获取
锁定直到锁定被释放。

很明显,内部锁定范围与外部锁定范围位于同一线程中。

From section 8.12 of the C# language specification:

While a mutual-exclusion lock is held,
code executing in the same execution
thread can also obtain and release the
lock. However, code executing in other
threads is blocked from obtaining the
lock until the lock is released.

It should be obvious that the internal lock scope is in the same thread as the outer.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文