SYSK 213: Curious to Know How C# lock Keyword is Actually Implemented? Then read on…
We know that C# keywords are simply programming language (in this case, C#) lingo that map into the .NET framework types, objects, etc. So, what does the ‘lock’ keyword map to? Through the simple use of ildasm tool, you can see that the lock keyword ends up being a call to System.Threading.Monitor.Enter/Exit. Consider the following simple code snippet:
object someObject = new object();
. . .
private void button1_Click(object sender, EventArgs e)
{
lock(someObject)
{
// Your code here
}
}
In IL, it’s represented by the following instruction set:
.method private hidebysig instance void button1_Click(object sender, class [mscorlib]System.EventArgs e) cil managed
{
// Code size 29 (0x1d)
.maxstack 2
.locals init ([0] object CS$2$0000)
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldfld object WindowsApplication1.Form1::someObject
IL_0007: dup
IL_0008: stloc.0
IL_0009: call void [mscorlib]System.Threading.Monitor::Enter(object)
IL_000e: nop
.try
{
IL_000f: nop
IL_0010: nop
IL_0011: leave.s IL_001b
} // end .try
finally
{
IL_0013: ldloc.0
IL_0014: call void [mscorlib]System.Threading.Monitor::Exit(object)
IL_0019: nop
IL_001a: endfinally
} // end handler
IL_001b: nop
IL_001c: ret
} // end of method Form1::button1_Click
Now consider the following:
private void button1_Click(object sender, EventArgs e)
{
System.Threading.Monitor.Enter(someObject);
try
{
// Your code here
}
finally
{
System.Threading.Monitor.Exit(someObject);
}
}
The resulting IL is almost identical to the one produced by the lock keyword:
.method private hidebysig instance void button1_Click(object sender, class [mscorlib]System.EventArgs e) cil managed
{
// Code size 34 (0x22)
.maxstack 1
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldfld object WindowsApplication1.Form1::someObject
IL_0007: call void [mscorlib]System.Threading.Monitor::Enter(object)
IL_000c: nop
.try
{
IL_000d: nop
IL_000e: nop
IL_000f: leave.s IL_0020
} // end .try
finally
{
IL_0011: nop
IL_0012: ldarg.0
IL_0013: ldfld object WindowsApplication1.Form1::someObject
IL_0018: call void [mscorlib]System.Threading.Monitor::Exit(object)
IL_001d: nop
IL_001e: nop
IL_001f: endfinally
} // end handler
IL_0020: nop
IL_0021: ret
} // end of method Form1::button1_Click