线程同步之lock学习
在应用程序中使用多个线程的一个好处是每个线程都可以异步执行。然而,线程的异步特性意味着必须协调对资源(如文件句柄、网络连接和内存)的访问。否则,两个或更多的线程可能在同一时间访问相同的资源,而每个线程都不知道其他线程的操作。结果将产生不可预知的数据损坏。这个时候我们就需要lock上场了。
Lock的作用
Lock获取给定对象的互斥锁,保证相应的代码块运行时,不会被其他线程中断;直到该对象被释放时其他线程才能访问相应的代码块;
Lock实现本质
通过System.Threading.Monitor的enter和exit方法实现的
代码实例如下

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代码如下

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的参数必须为引用类型的对象,该对象代表了锁定的范围,对象不同锁定的范围也不同。
锁定参数为待锁定代码块内声明的对象,锁定范围为该代码块

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 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 (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 (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的地方

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

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相同

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 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 }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现