I expect the following code to deadlock when Clear tries to lock on the same object that Build has already locked:
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");
}
}
}
Output:
Clear
Build
Edit 1
Thank you all for your answers.
If I add a call to Build inside the lock of Clear (keeping the rest of the code the same):
public void Clear()
{
lock (_lock)
{
Build();
Console.WriteLine("Clear");
}
}
A deadlock does occur (or at least that’s what I think, LINQ Pad crashes).
According to your answers, this shouldn’t happen, because it’s still the same thread.
Thanks!
In C#, a thread holding a lock can enter the same lock without blocking.
The
lockstatement, as well as the Monitor class on which it is built, is reentrant in .NET.Edit in response to your edit:
When you add the call to
Buildinside clear, the code doesn’t deadlock – it is calling itself recursively. It’s not blocking, but rather running forever (until, eventually, you hit a StackOverflowException), becauseBuildcallsClearwhich callsBuildagain which callsClear, etc….