在应用程序中使用多个线程的一个好处是每个线程都可以异步执行。然而,线程的异步特性意味着必须协调对资源(如文件句柄、网络连接和内存)的访问。否则,两个或更多的线程可能在同一时间访问相同的资源,而每个线程都不知道其他线程的操作。结果将产生不可预知的数据损坏。这个时候我们就需要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 }
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
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }