在应用程序中使用多个线程的一个好处是每个线程都可以异步执行。然而,线程的异步特性意味着必须协调对资源(如文件句柄、网络连接和内存)的访问。否则,两个或更多的线程可能在同一时间访问相同的资源,而每个线程都不知道其他线程的操作。结果将产生不可预知的数据损坏。这个时候我们就需要lock上场了。
Lock的作用
Lock获取给定对象的互斥锁,保证相应的代码块运行时,不会被其他线程中断;直到该对象被释放时其他线程才能访问相应的代码块;
Lock实现本质
通过System.Threading.Monitor的enter和exit方法实现的
代码实例如下
View Code
1 public void PrintByInnerObj( object greating) 2 { 3 Console.WriteLine(greating + " -- before lock " ); 4 object obj = new object (); 5 lock (obj) 6 { 7 Console.WriteLine(greating + " -- is locking " ); 8 Console.WriteLine(greating.ToString()); 9 System.Threading.Thread.Sleep( 10000 ); 10 } 11 Console.WriteLine(greating + " -- has unlock " ); 12 }
对应的MSIL代码如下
View Code
1 .method public hidebysig instance void PrintByInnerObj( object greating) cil managed 2 { 3 // Code size 116 (0x74) 4 .maxstack 2 5 .locals init ([ 0 ] object obj, 6 [ 1 ] bool ' <>s__LockTaken0 ' , 7 [ 2 ] object CS$ 2 $ 0000 , 8 [ 3 ] bool CS$ 4 $ 0001 ) 9 IL_0000: nop 10 IL_0001: ldarg.1 11 IL_0002: ldstr " -- before lock " 12 IL_0007: call string [mscorlib]System.String::Concat( object , 13 object ) 14 IL_000c: call void [mscorlib]System.Console::WriteLine( string ) 15 IL_0011: nop 16 IL_0012: newobj instance void [mscorlib]System.Object::.ctor() 17 IL_0017: stloc.0 18 IL_0018: ldc.i4.0 19 IL_0019: stloc.1 20 .try 21 { 22 IL_001a: ldloc.0 23 IL_001b: dup 24 IL_001c: stloc.2 25 IL_001d: ldloca.s ' <>s__LockTaken0 ' 26 IL_001f: call void [mscorlib]System.Threading.Monitor::Enter( object , 27 bool &) 28 IL_0024: nop 29 IL_0025: nop 30 IL_0026: ldarg.1 31 IL_0027: ldstr " -- is locking " 32 IL_002c: call string [mscorlib]System.String::Concat( object , 33 object ) 34 IL_0031: call void [mscorlib]System.Console::WriteLine( string ) 35 IL_0036: nop 36 IL_0037: ldarg.1 37 IL_0038: callvirt instance string [mscorlib]System.Object::ToString() 38 IL_003d: call void [mscorlib]System.Console::WriteLine( string ) 39 IL_0042: nop 40 IL_0043: ldc.i4 0x2710 41 IL_0048: call void [mscorlib]System.Threading.Thread::Sleep( int32 ) 42 IL_004d: nop 43 IL_004e: nop 44 IL_004f: leave .s IL_0061 45 } // end .try 46 finally 47 { 48 IL_0051: ldloc.1 49 IL_0052: ldc.i4.0 50 IL_0053: ceq 51 IL_0055: stloc.3 52 IL_0056: ldloc.3 53 IL_0057: brtrue.s IL_0060 54 IL_0059: ldloc.2 55 IL_005a: call void [mscorlib]System.Threading.Monitor::Exit( object ) 56 IL_005f: nop 57 IL_0060: endfinally 58 } // end handler 59 IL_0061: nop 60 IL_0062: ldarg.1 61 IL_0063: ldstr " -- has unlock " 62 IL_0068: call string [mscorlib]System.String::Concat( object , 63 object ) 64 IL_006d: call void [mscorlib]System.Console::WriteLine( string ) 65 IL_0072: nop 66 IL_0073: ret 67 } // end of method MyLockTest::PrintByInnerObj
Lock的锁定范围
Lock的参数必须为引用类型的对象,该对象代表了锁定的范围,对象不同锁定的范围也不同。
锁定参数为待锁定代码块内声明的对象,锁定范围为该代码块
View Code
1 public void PrintByInnerObj(objectgreating) 2 3 { 4 5 Console.WriteLine(greating + " -- before lock " ); 6 7 object obj = newobject(); 8 9 lock (obj) 10 11 { 12 13 Console.WriteLine(greating + " -- is locking " ); 14 15 Console.WriteLine(greating.ToString()); 16 17 System.Threading.Thread.Sleep( 10000 ); 18 19 } 20 21 Console.WriteLine(greating + " -- has unlock " ); 22 23 }
锁定参数为待锁定代码块所在类的私有字段,锁定范围为该类具体的一个实例
View Code
1 public void PrintByInstanceObj(objectgreating) 2 3 { 4 5 Console.WriteLine(greating + " -- before lock " ); 6 7 lock (instanceObj) 8 9 { 10 11 Console.WriteLine(greating + " -- is locking " ); 12 13 Console.WriteLine(greating.ToString()); 14 15 System.Threading.Thread.Sleep( 10000 ); 16 17 } 18 19 Console.WriteLine(greating + " -- has unlock " ); 20 21 }
锁定参数为待锁定代码块所在类的私有静态字段,锁定范围为该类所有的实例
View Code
1 public void PrintLockByStaticObj(objectgreating) 2 3 { 4 5 Console.WriteLine(greating + " -- before lock " ); 6 7 lock (staticObj) 8 9 { 10 11 Console.WriteLine(greating + " -- is locking " ); 12 13 Console.WriteLine(greating.ToString()); 14 15 Thread.Sleep( 10000 ); 16 17 } 18 19 Console.WriteLine(greating + " -- has unlock " ); 20 21 }
锁定参数为某一字符串,锁定范围为与该字符串值相等的所有字符串
View Code
1 public void PrintLockByStringObj(objectgreating) 2 3 { 4 5 Console.WriteLine(greating + " -- before lock " ); 6 7 lock (stringObj) 8 9 { 10 11 Console.WriteLine(greating + " -- is locking " ); 12 13 Console.WriteLine(greating.ToString()); 14 15 System.Threading.Thread.Sleep( 10000 ); 16 17 } 18 19 Console.WriteLine(greating + " --has unlock " ); 20 21 } 22 23 24 public void PrintLockByString(objectgreating) 25 26 { 27 28 Console.WriteLine(greating + " -- before lock " ); 29 30 lock ( " lock " ) 31 32 { 33 34 Console.WriteLine(greating + " -- is locking " ); 35 36 Console.WriteLine(greating.ToString()); 37 38 System.Threading.Thread.Sleep( 10000 ); 39 40 } 41 42 Console.WriteLine(greating + " --has unlock " ); 43 44 }
锁定参数为this,锁定范围为所有能访问到this的地方
View Code
1 public void PrintLockByThis(objectgreating) 2 3 { 4 5 Console.WriteLine(greating + " -- before lock " ); 6 7 lock ( this ) 8 9 { 10 11 Console.WriteLine(greating + " -- is locking " ); 12 13 Console.WriteLine(greating.ToString()); 14 15 System.Threading.Thread.Sleep( 10000 ); 16 17 } 18 19 Console.WriteLine(greating + " --has unlock " ); 20 21 }
锁定参数为某个类的System.Type的实例,锁定范围为所有的地方
锁定public的实例字段,锁定范围同锁定this
View Code
1 public void PrintLockByPublicInstanceObj(objectgreating) 2 3 { 4 5 Console.WriteLine(greating + " -- before lock " ); 6 7 lock (publicInstanceObj) 8 9 { 10 11 Console.WriteLine(greating + " -- is locking " ); 12 13 Console.WriteLine(greating.ToString()); 14 15 System.Threading.Thread.Sleep( 10000 ); 16 17 } 18 19 Console.WriteLine(greating + " --has unlock " ); 20 21 }
锁定参数为public的静态字段,锁定范围与锁定system.type相同
View Code
1 public void PrintLockByPublicStaticObj(objectgreating) 2 3 { 4 5 Console.WriteLine(greating + " -- before lock " ); 6 7 lock (publicStaticObj) 8 9 { 10 11 Console.WriteLine(greating + " -- is locking " ); 12 13 Console.WriteLine(greating.ToString()); 14 15 System.Threading.Thread.Sleep( 10000 ); 16 17 } 18 19 Console.WriteLine(greating + " --has unlock " ); 20 21 }
整个类的代码如下
View Code
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading; 6 7 namespace LockCVolatileCA 8 { 9 public class MyLockTest 10 { 11 private static object staticObj = new object (); 12 private object instanceObj = new object (); 13 public static object publicStaticObj = new object (); 14 public object publicInstanceObj = new object (); 15 private string stringObj = " lock " ; 16 private static Int32 i = new int () ; 17 18 public void PrintByInnerObj( object greating) 19 { 20 Console.WriteLine(greating + " -- before lock " ); 21 object obj = new object (); 22 lock (obj) 23 { 24 Console.WriteLine(greating + " -- is locking " ); 25 Console.WriteLine(greating.ToString()); 26 System.Threading.Thread.Sleep( 10000 ); 27 } 28 Console.WriteLine(greating + " -- has unlock " ); 29 } 30 31 public void PrintByInstanceObj( object greating) 32 { 33 Console.WriteLine(greating + " -- before lock " ); 34 lock (instanceObj) 35 { 36 Console.WriteLine(greating + " -- is locking " ); 37 Console.WriteLine(greating.ToString()); 38 System.Threading.Thread.Sleep( 10000 ); 39 } 40 Console.WriteLine(greating + " -- has unlock " ); 41 } 42 43 public void PrintLockByStaticObj( object greating) 44 { 45 Console.WriteLine(greating + " -- before lock " ); 46 lock (staticObj) 47 { 48 Console.WriteLine(greating + " -- is locking " ); 49 Console.WriteLine(greating.ToString()); 50 Thread.Sleep( 10000 ); 51 } 52 Console.WriteLine(greating + " -- has unlock " ); 53 } 54 55 public void PrintLockByClass( object greating) 56 { 57 Console.WriteLine(greating + " -- before lock " ); 58 lock ( typeof (MyLockTest)) 59 { 60 Console.WriteLine(greating + " -- is locking " ); 61 Console.WriteLine(greating.ToString()); 62 Thread.Sleep( 1000 ); 63 } 64 Console.WriteLine(greating + " -- has unlock " ); 65 } 66 67 public void PrintLockByThis( object greating) 68 { 69 Console.WriteLine(greating + " -- before lock " ); 70 lock ( this ) 71 { 72 Console.WriteLine(greating + " -- is locking " ); 73 Console.WriteLine(greating.ToString()); 74 System.Threading.Thread.Sleep( 10000 ); 75 } 76 Console.WriteLine(greating + " --has unlock " ); 77 } 78 79 public void PrintLockByStringObj( object greating) 80 { 81 Console.WriteLine(greating + " -- before lock " ); 82 lock (stringObj) 83 { 84 Console.WriteLine(greating + " -- is locking " ); 85 Console.WriteLine(greating.ToString()); 86 System.Threading.Thread.Sleep( 10000 ); 87 } 88 Console.WriteLine(greating + " --has unlock " ); 89 } 90 91 public void PrintLockByString( object greating) 92 { 93 Console.WriteLine(greating + " -- before lock " ); 94 lock ( " lock " ) 95 { 96 Console.WriteLine(greating + " -- is locking " ); 97 Console.WriteLine(greating.ToString()); 98 System.Threading.Thread.Sleep( 10000 ); 99 } 100 Console.WriteLine(greating + " --has unlock " ); 101 } 102 103 public void PrintLockByPublicStaticObj( object greating) 104 { 105 Console.WriteLine(greating + " -- before lock " ); 106 lock (publicStaticObj) 107 { 108 Console.WriteLine(greating + " -- is locking " ); 109 Console.WriteLine(greating.ToString()); 110 System.Threading.Thread.Sleep( 10000 ); 111 } 112 Console.WriteLine(greating + " --has unlock " ); 113 } 114 115 public void PrintLockByPublicInstanceObj( object greating) 116 { 117 Console.WriteLine(greating + " -- before lock " ); 118 lock (publicInstanceObj) 119 { 120 Console.WriteLine(greating + " -- is locking " ); 121 Console.WriteLine(greating.ToString()); 122 System.Threading.Thread.Sleep( 10000 ); 123 } 124 Console.WriteLine(greating + " --has unlock " ); 125 } 126 } 127 }