在应用程序中使用多个线程的一个好处是每个线程都可以异步执行。然而,线程的异步特性意味着必须协调对资源(如文件句柄、网络连接和内存)的访问。否则,两个或更多的线程可能在同一时间访问相同的资源,而每个线程都不知道其他线程的操作。结果将产生不可预知的数据损坏。这个时候我们就需要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代码如下
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
}
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 }
锁定参数为待锁定代码块所在类的私有字段,锁定范围为该类具体的一个实例
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
锁定参数为待锁定代码块所在类的私有静态字段,锁定范围为该类所有的实例
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
}
锁定参数为某一字符串,锁定范围为与该字符串值相等的所有字符串
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
}
锁定参数为this,锁定范围为所有能访问到this的地方
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
}
锁定参数为某个类的System.Type的实例,锁定范围为所有的地方
锁定public的实例字段,锁定范围同锁定this
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
}
锁定参数为public的静态字段,锁定范围与锁定system.type相同
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
}
整个类的代码如下
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
}
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
}
整个类的代码如下
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
}