Each object receives a 4-byte "block" of allocated memory (syncblk), which is an index in SyncTableEntry. When an object is created, syncblk is set to 0, which prevents additional memory allocation (except for this 4 byte numbers). When the lock is executed, this synchronization is set to the corresponding record in the table, which can then cause distribution. This is essentially lazy initialization.
When you call lock (object), it effectively uses Monitor.Enter for the object, which in turn sets the record correctly. For more information, see the MSDN Article in .NET Internal Languages .
source share