个人随笔
技术改变世界

C#中的Monitor与Lock的区别

实际上Lock就是Monitor,而唯一的区别就是使用Lock时在生成IL代码时加上了try

如下所示的两种代码是相等的

lock(obj)
{
    dosomething();
}

(代码一)

 

 try
 {
    Monitor.Enter(obj);
    dosomething();
 }
 catch(Exception ex)
 {
 
 }
 finally
 {
    Monitor.Exit(obj);
 }

(代码二)

至此,我想你应该明白了它们的区别。当我们追求性能的时候,则不会使用lock,而是使用Monitor这样可以避免try语句所消耗的性能。

 

以下是我编写的简单的一段代码以及IL中间代码示例。

 /// <summary>
 /// lock对象
 /// </summary>
 private static object _myLock = new object();

 static void Main(string[] args)
 {
     lock (_myLock)
     {
         Console.WriteLine("lock()");
     }

     System.Threading.Monitor.Enter(_myLock);
     Console.WriteLine("Monitor()");
     System.Threading.Monitor.Exit(_myLock);

     Console.ReadLine();
 }

该段代码分别写了lockmonitor,以下是通过ILDasm.exe查看所生成的IL中间代码:

.method private hidebysig static void Main(string[] args) cil managed
{
 .entrypoint
 // 代码大小 90 (0x5a)
 .maxstack 2
 .locals init ([0] bool '<>s__LockTaken0',
         [1] object CS$2$0000,
         [2] bool CS$4$0001)
 IL_0000: nop
 IL_0001: ldc.i4.0
 IL_0002: stloc.0
 .try
 {
   IL_0003: ldsfld object Monitor_Lock.Program::_myLock
   IL_0008: dup
   IL_0009: stloc.1
   IL_000a: ldloca.s '<>s__LockTaken0'
   IL_000c: call void [mscorlib]System.Threading.Monitor::Enter(object,
   bool&)
   IL_0011: nop
   IL_0012: nop
   IL_0013: ldstr "lock()"
   IL_0018: call void [mscorlib]System.Console::WriteLine(string)
   IL_001d: nop
   IL_001e: nop
   IL_001f: leave.s IL_0031
 } // end .try
 finally
 {
   IL_0021: ldloc.0
   IL_0022: ldc.i4.0
   IL_0023: ceq
   IL_0025: stloc.2
   IL_0026: ldloc.2
   IL_0027: brtrue.s IL_0030
   IL_0029: ldloc.1
   IL_002a: call void [mscorlib]System.Threading.Monitor::Exit(object)
   IL_002f: nop
   IL_0030: endfinally
 } // end handler
 IL_0031: nop
 IL_0032: ldsfld object Monitor_Lock.Program::_myLock
 IL_0037: call void [mscorlib]System.Threading.Monitor::Enter(object)
 IL_003c: nop
 IL_003d: ldstr "Monitor()"
 IL_0042: call void [mscorlib]System.Console::WriteLine(string)
 IL_0047: nop
 IL_0048: ldsfld object Monitor_Lock.Program::_myLock
 IL_004d: call void [mscorlib]System.Threading.Monitor::Exit(object)
 IL_0052: nop
 IL_0053: call string [mscorlib]System.Console::ReadLine()
 IL_0058: pop
 IL_0059: ret
} // end of method Program::Main

仔细看下,应该都能看的明白吧,正如我们前面所述lock部分的代码被try了起来。

转载请注明出处王旭博客 » C#中的Monitor与Lock的区别

分享到:更多 ()

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址