What does a lock statement do under the hood?

C#.NetSynchronizationLockingThread Safety

C# Problem Overview


I see that for using objects which are not thread safe we wrap the code with a lock like this:

private static readonly Object obj = new Object();

lock (obj)
{
    // thread unsafe code
}

So, what happens when multiple threads access the same code (let's assume that it is running in a ASP.NET web application). Are they queued? If so how long will they wait?

What is the performance impact because of using locks?

C# Solutions


Solution 1 - C#

The lock statement is translated by C# 3.0 to the following:

var temp = obj;

Monitor.Enter(temp);

try
{
    // body
}
finally
{
    Monitor.Exit(temp);
}

In C# 4.0 this has changed and it is now generated as follows:

bool lockWasTaken = false;
var temp = obj;
try
{
    Monitor.Enter(temp, ref lockWasTaken);
    // body
}
finally
{
    if (lockWasTaken)
    {
        Monitor.Exit(temp); 
    }
}

You can find more info about what Monitor.Enter does here. To quote MSDN:

> Use Enter to acquire the Monitor on > the object passed as the parameter. If > another thread has executed an Enter > on the object but has not yet executed > the corresponding Exit, the current > thread will block until the other > thread releases the object. It is > legal for the same thread to invoke > Enter more than once without it > blocking; however, an equal number of > Exit calls must be invoked before > other threads waiting on the object > will unblock.

The Monitor.Enter method will wait infinitely; it will not time out.

Solution 2 - C#

Its simpler than you think-

According to Microsoft: The lock keyword ensures that one thread does not enter a critical section of code while another thread is in the critical section. If another thread tries to enter a locked code, it will wait, block, until the object is released.

The lock keyword calls Enter at the start of the block and Exit at the end of the block. lock keyword actually handles Monitor class at back end.

For example:

private static readonly Object obj = new Object();

lock (obj)
{
    // critical section
}

In the above code, first the thread enters a critical section, and then it will lock obj. When another thread tries to enter, it will also try to lock obj, which is already locked by the first thread. Second thread will have to wait for the first thread to release obj. When the first thread leaves, then another thread will lock obj and will enter the critical section.

Solution 3 - C#

No, they are not queued, they are sleeping

A lock statement of the form

lock (x) ... 

where x is an expression of a reference-type, is precisely equivalent to

var temp = x;
System.Threading.Monitor.Enter(temp); 
try { ... } 
finally { System.Threading.Monitor.Exit(temp); }

You just need to know that they are waiting to each other, and only one thread will enter to lock block, the others will wait...

Monitor is written fully in .net so it is enough fast, also look at class Monitor with reflector for more details

Solution 4 - C#

Locks will block other threads from executing the code contained in the lock block. The threads will have to wait until the thread inside the lock block has completed and the lock is released. This does have a negative impact on performance in a multithreaded environment. If you do need to do this you should make sure the code within the lock block can process very quickly. You should try to avoid expensive activities like accessing a database etc.

Solution 5 - C#

The performance impact depends on the way you lock. You can find a good list of optimizations here: http://www.thinkingparallel.com/2007/07/31/10-ways-to-reduce-lock-contention-in-threaded-programs/

Basically you should try to lock as little as possible, since it puts your waiting code to sleep. If you have some heavy calculations or long lasting code (e.g. file upload) in a lock it results in a huge performance loss.

Solution 6 - C#

The part within the lock statement can only be executed by one thread, so all other threads will wait indefinitely for it the thread holding the lock to finish. This can result in a so-called deadlock.

Solution 7 - C#

The lock statement is translated to calls to the Enter and Exit methods of Monitor.

The lock statement will wait indefinitely for the locking object to be released.

Solution 8 - C#

lock is actually hidden Monitor class.

Solution 9 - C#

According to Microsoft's MSDN, the lock is equivalent to:

object __lockObj = x;
bool __lockWasTaken = false;
try
{
    System.Threading.Monitor.Enter(__lockObj, ref __lockWasTaken);
    // Your code...
}
finally
{
    if (__lockWasTaken) System.Threading.Monitor.Exit(__lockObj);
}

If you need to create locks in runtime, you can use open source DynaLock. You can create new locks in run-time and specify boundaries to the locks with context concept.

DynaLock is open-source and source code is available at GitHub

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
QuestionNLVView Question on Stackoverflow
Solution 1 - C#StevenView Answer on Stackoverflow
Solution 2 - C#Umar AbbasView Answer on Stackoverflow
Solution 3 - C#Arsen MkrtchyanView Answer on Stackoverflow
Solution 4 - C#AndrewView Answer on Stackoverflow
Solution 5 - C#Simon WokerView Answer on Stackoverflow
Solution 6 - C#Mr47View Answer on Stackoverflow
Solution 7 - C#Paolo TedescoView Answer on Stackoverflow
Solution 8 - C#EuphoricView Answer on Stackoverflow
Solution 9 - C#Saeed AghdamView Answer on Stackoverflow