为什么这段代码没有死锁

本文关键字:死锁 代码 段代码 为什么 | 更新日期: 2023-09-27 18:34:25

我希望当 Clear 尝试锁定 Build 已锁定的同一对象时,以下代码将死锁:

void Main()
{
    (new SiteMap()).Build();
}
class SiteMap
{
    private readonly object _lock = new object();
    public void Build()
    {
        lock (_lock)
        {
            Clear();
            Console.WriteLine("Build");
        }
    }
    public void Clear()
    {
        lock (_lock)
        {
            Console.WriteLine("Clear");
        }
    }
}

输出:

清楚

编辑 1

谢谢大家的回答。

如果我在 Clear 锁中添加对 Build 的调用(保持代码的其余部分相同):

public void Clear()
{
    lock (_lock)
    {
        Build();
        Console.WriteLine("Clear");
    }
}

确实会发生死锁(或者至少我认为是这样,LINQ Pad 崩溃)。

根据您的回答,这不应该发生,因为它仍然是相同的线程。

谢谢!

为什么这段代码没有死锁

在 C# 中,持有锁的线程可以进入同一锁而不会阻塞。

lock语句以及生成该语句的监视器类在 .NET 中是可重入的。


编辑

以响应您的编辑:

当您将调用添加到 clear 内部Build时,代码不会死锁 - 它会递归调用自身。 它不是阻塞,而是永远运行(直到最终你遇到 StackOverflowException),因为Build调用Clear再次调用Build调用Clear,等等......

lock的文档说:

如果另一个线程尝试输入锁定的代码,它将等待(阻止)直到对象被释放。

关键词是"另一个"。线程不会阻塞自身,只会阻塞其他线程。如果另一个线程拥有锁,那么lock就会阻塞。

这样可以省去很多麻烦。

我不会,因为在已经应用锁的同一线程中调用了 clear。