I've been wondering recently how lock
(or more specific: Monitor
) works internally in .NET with regards to the objects that are locked. Specifically, I'm wondering what the overhead is, if there are 'global' (Process) locks used, if it's possible to create more of those global locks if that's the case (for groups of monitors) and what happens to the objects that are passed to lock (they don't seem to introduce an extra memory overhead).
To clarify what I'm not asking about: I'm not asking here about what a Monitor is (I made one myself at University some time ago). I'm also not asking how to use lock
, Monitor, how they compile to a try/finally, etc; I'm pretty well aware of that (and there are other SO questions related to that). This is about the inner workings of Monitor.Enter
and Monitor.Exit
.
For example, consider this code executed by ten threads:
for (int i=0; i<1000; ++i)
{
lock (myArray[i])
{
// ...
}
}
Monitor.Enter
is not a normal .NET method (can't be decompiled with ILSpy or similar). The method is implemented internally by the CLR, so strictly speaking, there is no one answer for .NET as different runtimes can have different implementations.
All objects in .NET have an object header containing a pointer to the type of the object, but also an SyncBlock
index into a SyncTableEntry
. Normally that index is zero/non used, but when you lock on the object it will contain an index into the SyncTableEntry
which then contains the reference to the actual lock object.
So locking of thousands of objects will indeed create a lot of locks which is an overhead.
The information I found was in this MSDN article: http://msdn.microsoft.com/en-us/magazine/cc163791.aspx