当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崩溃了。)
根据你的回答,这不应该发生,因为它仍然是同一个线程。
谢谢!
答案 0 :(得分:8)
在C#中,持有锁的线程可以不阻塞地进入同一个锁。
lock
语句以及构建它的Monitor class在.NET中为reentrant。
编辑以响应您的修改:
当您将调用添加到Build
内部时,代码不会死锁 - 它会以递归方式调用自身。这不是阻止,而是永远运行(直到最终,你点击StackOverflowException),因为Build
调用Clear
再次调用Build
它调用Clear
等......
答案 1 :(得分:5)
lock
的文档说:
如果另一个线程试图输入锁定的代码,它将等待(阻止)直到该对象被释放。
关键词是“另一个”。线程不会阻塞自己,只阻塞其他线程。如果另一个线程拥有锁,那么lock
将阻止。
这可以避免很多麻烦。
答案 2 :(得分:4)
我不会因为在已经应用锁定的同一个线程中调用clear。