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