Why do nested locks not cause a deadlock?

C#asp.netDeadlock

C# Problem Overview


Why does this code not cause a deadlock?

   private static readonly object a = new object();

...

   lock(a)
   {
      lock(a)
      {
         ....
      }
   }

C# Solutions


Solution 1 - C#

If a thread already holds a lock, then it can "take that lock" again without issue.


As to why that is, (and why it's a good idea), consider the following situation, where we have a defined lock ordering elsewhere in the program of a -> b:

void f()
{
    lock(a)
    { /* do stuff inside a */ }
}

void doStuff()
{
    lock(b)
    {
        //do stuff inside b, that involves leaving b in an inconsistent state
        f();
        //do more stuff inside b so that its consistent again
    }
}

Whoops, we just violated our lock ordering and have a potential deadlock on our hands.

We really need to be able to do the following:

function doStuff()
{
    lock(a)
    lock(b)
    {
        //do stuff inside b, that involves leaving b in an inconsistent state
        f();
        //do more stuff inside b so that its consistent again
    }
}

So that our lock ordering is maintained, without self-deadlocking when we call f().

Solution 2 - C#

The lock keyword uses a re-entrant lock, meaning the current thread already has the lock so it doesn't try to reacquire it.

A deadlock occurs if

Thread 1 acquires lock A
Thread 2 acquires lock B
Thread 1 tries to acquire lock B (waits for Thread 2 to be done with it) Thread 2 tries to acquire lock A (waits for Thread 1 to be done with it)

Both threads are now waiting on each other and thus deadlocked.

Solution 3 - C#

From section 8.12 of the C# language specification:

> While a mutual-exclusion lock is held, > code executing in the same execution > thread can also obtain and release the > lock. However, code executing in other > threads is blocked from obtaining the > lock until the lock is released.

It should be obvious that the internal lock scope is in the same thread as the outer.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionMysterView Question on Stackoverflow
Solution 1 - C#Anon.View Answer on Stackoverflow
Solution 2 - C#Davy8View Answer on Stackoverflow
Solution 3 - C#Dan JView Answer on Stackoverflow