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 u
lock (obj)
{
}
was just syntactic sugar for Monitor.Enter in a try...finally.
Monitor.Enter(obj);
try
{
}
finally
{
Monitor.Exit(obj);
}
It is now something a little better (Thanks to Mark and Adriano for keeping me current).
bool locked = false;
try
{
Monitor.Enter(_syncRoot, ref locked);
}
finally
{
if (locked)
Monitor.Exit(_syncRoot);
}
This is Microsoft documentation saying lock() wraps Monitor.Enter/Exit
"use the C# lock statement, which wraps the Enter and Exit methods in a try…finally block."
from http://msdn.microsoft.com/en-us/library/de0542zz.aspx
If you want a spinlock type you can use ReaderWriterLockSlim()
http://msdn.microsoft.com/en-us/library/system.threading.readerwriterlockslim.aspx
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).