2012-05-17 55 views
5

我期待下面的代码时,清除试图锁定该建设已经锁定了同一个对象上死锁:为什么这段代码不会死锁?

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

谢谢大家的回答。

如果我添加一个呼叫清除的锁内建设(保持同一代码的其余部分):

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

     Console.WriteLine("Clear"); 
    } 
} 

死锁不会发生(或至少这是我的想法,LINQ垫崩溃)。

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

谢谢!

+1

请参阅http://www.albahari.com/threading/part2.aspx,在“嵌套锁定”下。 –

回答

8

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

lock声明以及它在其上构建的Monitor class在.NET中为reentrant


编辑回应您的编辑:

当您添加调用Build里面清晰,代码不会死锁 - 它是递归调用本身。这不是,而是永远跑(直到最后,你打一个StackOverflowException),因为Build电话Clear再次这就要求Clear要求Build等....

+0

关于我的编辑,我真的不知道我没有看到。谢谢你的答案! – stacker

4

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

5

lock文档说:

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

关键词是“另一个”。一个线程不会阻塞自己,只是其他线程。如果另一个线程拥有该锁,则lock会阻止。

这节省了很多头痛。