Does the c# lock keyword use a 'yielding', 'spin-locking' or hybrid approach to handle contention?
So far my searches on the .net lock statement hasn't turned up an answer. I will post if I do find any more. So far all I could find is When should one use a spinlock ... with a nicely worded accepted answer by Mecki.
But I am looking for some definitive answer or documentation regarding .net/c# if anyone has one.
The lock statement acquires the mutual-exclusion lock for a given object, executes a statement block, and then releases the lock. While a lock is held, the thread that holds the lock can again acquire and release the lock. Any other thread is blocked from acquiring the lock and waits until the lock is released.
A locking mechanism is a mechanical system which provides assistance to the coupling and uncoupling of two connectors and the fixation of the two parts in operating position. The locking system helps to maintain the primary function of electrical continuity and is involved in the sealing performances of products.
A lock may be a tool for controlling access to a shared resource by multiple threads. Commonly, a lock provides exclusive access to a shared resource: just one thread at a time can acquire the lock and everyone accesses to the shared resource requires that the lock be acquired first.
Following code:
lock (_syncRoot)
{
// Do stuff
}
Is translated by the compiler to:
Monitor.Enter(_syncRoot)
try
{
// Do stuff
}
finally
{
Monitor.Exit(_syncRoot);
}
This is the naive (and old) implementation, actually with .NET 4.0 the implementation is more or less this (see Eric's blog for complete reference):
bool locked = false;
try
{
Monitor.Enter(_syncRoot, ref locked);
}
finally
{
if (locked)
Monitor.Exit(_syncRoot);
}
EDITED
That said the question is how Monitor.Enter()
works? Well, default Mono implementation uses a semaphore to acquire the lock but Microsoft .NET implementation acts different.
I was reading Concurrent Windows Programming (by Joe Duffy) when a paragraph did catch my attention, my first answer said "no, it doesn't use spinning because performance may not be good in general cases". Correct answer is "yes, .NET Monitor
uses spinning". Both .NET Monitor
and Windows Critical Sections perform a short spinning before falling back to a true wait on a kernel object. This algorithm is called "two-phase locking protocol" and it's appropriate because context switches and kernel transitions are very expansive, on a multiprocessor machine spinning can avoid both of them.
Moreover do not forget these are implementation details and can change in any release (or algorithm can be different for different hardwares because of JIT compiler).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With