Problem
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 if many threads visit the same code (assuming it’s in an ASP.NET web application)? Is there a line? If that’s the case, how long will they have to wait?
What effect does the use of locks have on performance?
Asked by NLV
Solution #1
C# 3.0 translates the lock statement to the following:
var temp = obj;
Monitor.Enter(temp);
try
{
// body
}
finally
{
Monitor.Exit(temp);
}
This has changed in C# 4.0, and it now looks like this:
bool lockWasTaken = false;
var temp = obj;
try
{
Monitor.Enter(temp, ref lockWasTaken);
// body
}
finally
{
if (lockWasTaken)
{
Monitor.Exit(temp);
}
}
More information regarding Monitor.Enter can be found here. To paraphrase MSDN:
The Monitor is a fictional character. The Enter method will not time out and will wait indefinitely.
Answered by Steven
Solution #2
It’s a lot easier than you think-
The lock keyword ensures that one thread does not enter a vital part of code while another thread is in the critical region, according to Microsoft. If another thread tries to enter a locked code, it will wait until the object is freed before proceeding.
The lock keyword is used to call Enter at the beginning of the block and exit at the end. At the back end, the lock keyword manages the Monitor class.
For example:
private static readonly Object obj = new Object();
lock (obj)
{
// critical section
}
In the code above, the thread first accesses a critical region before locking obj. When a new thread tries to enter, it will also try to lock obj, which has already been locked by the previous thread. The second thread will have to wait for obj to be released by the first thread. When the first thread exits, another thread will lock onto the object and begin the critical portion.
Answered by Umar Abbas
Solution #3
They are not in line; instead, they are sleeping.
The form of a lock statement
lock (x) ...
where x is a reference-type expression, is exactly identical to
var temp = x;
System.Threading.Monitor.Enter(temp);
try { ... }
finally { System.Threading.Monitor.Exit(temp); }
All you need to know is that they’re waiting for each other, and that only one thread will enter the lock block while the others wait…
Monitor is written entirely in.net, making it extremely quick; for more information, see the class Monitor with Reflector.
Answered by Arsen Mkrtchyan
Solution #4
Other threads will be unable to execute the instructions contained in the lock block. The threads will have to wait till the lock is released and the thread inside the lock block has finished. In a multithreaded system, this has a negative influence on performance. If you do need to do this, make sure the code in the lock block can be processed rapidly. You should aim to avoid spending money on things like database access.
Answered by Andrew
Solution #5
The impact on performance is determined by how you lock. http://www.thinkingparallel.com/2007/07/31/10-ways-to-reduce-lock-contention-in-threaded-programs/ has a decent list of optimizations.
Generally speaking, you should lock as little as possible to avoid putting your waiting code to sleep. If you have some complex computations or long-running code (for example, a file upload) in a lock, you’ll notice a significant performance hit.
Answered by Simon Woker
Post is based on https://stackoverflow.com/questions/6029804/what-does-a-lock-statement-do-under-the-hood