为什么这段代码没有死锁?

sta*_*ker 5 c# deadlock locking thread-safety

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

输出:

明确

建立

编辑1

谢谢大家的答案.

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

public void Clear()
{
    lock (_lock)
    {
        Build();

        Console.WriteLine("Clear");
    }
}
Run Code Online (Sandbox Code Playgroud)

确实发生了死锁(或者至少就是我认为的那样,LINQ Pad崩溃).

根据你的答案,这不应该发生,因为它仍然是相同的线程.

谢谢!

Ree*_*sey 8

在C#中,持有锁的线程可以在不阻塞的情况下进入同一个锁.

lock语句以及构建它的Monitor类在.NET中是可重入的.


编辑以响应您的修改:

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


ike*_*ami 5

文档lock说:

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

关键词是"另一个".线程不会阻塞自己,只阻塞其他线程.如果另一个线程拥有锁,lock则会阻塞.

这节省了很多麻烦.