关于“GUI 博士的忠告:切勿锁定类型对象!”的实验
1
using System;
2
using System.Threading;
3
4
namespace TestLab.System.Threading
5
{
6
//在遇到线程类问题的时候,我们需要注意:
7
//a线程在执行“代码中连续的语句”a1、a2时,并不代表他们在实际执行时也是连续了(也许是连续的也许不是)
8
//也就是说此时b线程完全有可能在a1、a2之间做“小三”,这是上帝(CPU)的意思
9
internal class LowThread1
10
{
11
private static int _data;
12
private static object _lockObj = new object();
13
private string _name;
14
15
public int Data
16
{
17
get { return _data; }
18
}
19
20
public LowThread1(string name)
21
{
22
this._name = name;
23
Console.WriteLine("{1}创建新的LowLevel1对象:{0}", name, DateTime.Now);
24
}
25
26
public void FightOver1()
27
{
28
Console.WriteLine("{1}方法名:FightOver1------{0}", this._name, DateTime.Now);
29
Console.WriteLine("{2}线程名:{0}------{1}", Thread.CurrentThread.Name, this._name, DateTime.Now);
30
Console.WriteLine("{1}正在抢夺操作
------{0}", this._name, DateTime.Now);
31
32
lock (_lockObj)
33
{
34
Console.WriteLine("{2}线程名:{0} 开始操作资源
.------{1}", Thread.CurrentThread.Name, this._name, DateTime.Now);
35
_data++;
36
Console.WriteLine("{2}操作完毕,现在的数据值:{0}------{1}", _data, this._name, DateTime.Now);
37
Console.WriteLine("{1}开始Sleep 5 秒------{0}", this._name, DateTime.Now);
38
Thread.Sleep(5000);
39
}
40
41
Console.WriteLine("{2}线程名:{0} 已经离开操作------{1}", Thread.CurrentThread.Name, this._name, DateTime.Now);
42
}
43
public void FightOver2()
44
{
45
Console.WriteLine("{1}方法名:FightOver1------{0}", this._name, DateTime.Now);
46
Console.WriteLine("{2}线程名:{0}------{1}", Thread.CurrentThread.Name, this._name, DateTime.Now);
47
Console.WriteLine("{1}正在抢夺操作
------{0}", this._name, DateTime.Now);
48
49
lock(typeof(LowThread1))
50
{
51
Console.WriteLine("{2}线程:{0} 在LowLevel1.FightOver2()中开始睡 5 秒------{1}", Thread.CurrentThread.Name, this._name, DateTime.Now);
52
Thread.Sleep(5000);
53
}
54
Console.WriteLine("{2}线程名:{0} 已经离开操作------{1}", Thread.CurrentThread.Name, this._name, DateTime.Now);
55
}
56
public void FightOver3_1()
57
{
58
Console.WriteLine("{1}方法名:FightOver1------{0}", this._name, DateTime.Now);
59
Console.WriteLine("{2}线程名:{0}------{1}", Thread.CurrentThread.Name, this._name, DateTime.Now);
60
Console.WriteLine("{1}正在抢夺操作
------{0}", this._name, DateTime.Now);
61
62
lock (this)
63
{
64
Console.WriteLine("{2}线程:{0} 在LowLevel1.FightOver2()中开始睡 5 秒------{1}", Thread.CurrentThread.Name, this._name, DateTime.Now);
65
Thread.Sleep(5000);
66
}
67
Console.WriteLine("{2}线程名:{0} 已经离开操作------{1}", Thread.CurrentThread.Name, this._name, DateTime.Now);
68
}
69
public void FightOver3_2()
70
{
71
Console.WriteLine("{1}方法名:FightOver1------{0}", this._name, DateTime.Now);
72
Console.WriteLine("{2}线程名:{0}------{1}", Thread.CurrentThread.Name, this._name, DateTime.Now);
73
Console.WriteLine("{1}正在抢夺操作
------{0}", this._name, DateTime.Now);
74
75
lock (this)
76
{
77
Console.WriteLine("{2}线程:{0} 在LowLevel1.FightOver2()中开始睡 1 秒------{1}", Thread.CurrentThread.Name, this._name, DateTime.Now);
78
Thread.Sleep(1000);
79
}
80
Console.WriteLine("{2}线程名:{0} 已经离开操作------{1}", Thread.CurrentThread.Name, this._name, DateTime.Now);
81
}
82
}
83
public class LowThreadDrive1
84
{
85
public void Drive1()
86
{
87
LowThread1 ll1 = new LowThread1("name1");
88
LowThread1 ll2 = new LowThread1("name2");
89
90
Thread th1 = new Thread(ll1.FightOver1);
91
Thread th2 = new Thread(ll2.FightOver2);
92
93
th1.Name = "线程1";
94
th2.Name = "线程2";
95
96
th1.Start();
97
th2.Start();
98
99
}
100
public void Drive2()
101
{
102
LowThread1 ll1 = new LowThread1("ll1");
103
LowThreadHelp1 llh = new LowThreadHelp1("llh");
104
105
Thread th1 = new Thread(ll1.FightOver2);
106
Thread th2 = new Thread(llh.FightHelp2);
107
108
th1.Name = "线程1";
109
th2.Name = "线程2";
110
111
th1.Start();
112
Thread.Sleep(1000);
113
th2.Start();
114
}
115
public void Drive3()
116
{
117
LowThread1 ll1 = new LowThread1("ll1");
118
LowThreadHelp1 llh = new LowThreadHelp1("llh");
119
120
Thread th1 = new Thread(ll1.FightOver3_1);
121
Thread th2 = new Thread(llh.FightHelp3);
122
123
th1.Name = "线程1";
124
th2.Name = "线程2";
125
126
th1.Start();
127
Thread.Sleep(500);
128
th2.Start(ll1);
129
}
130
//注意 FightOver3和FightOver3_2()的不同之处在于lock块中,线程的sleep的时间前者5s后者1s
131
//此处只是锁住了LowThread1的一个实例,并不是所有的实例。不同实例调用lock(this)并不相关。
132
public void Drive4()
133
{
134
LowThread1 ll1 = new LowThread1("ll1");
135
LowThread1 ll2 = new LowThread1("ll2");
136
137
Thread th1 = new Thread(ll1.FightOver3_1);
138
Thread th2 = new Thread(ll2.FightOver3_2);
139
140
th1.Name = "线程1";
141
th2.Name = "线程2";
142
143
th1.Start();
144
Thread.Sleep(500);
145
th2.Start();
146
}
147
}
148
internal class LowThreadHelp1
149
{
150
private string _name;
151
152
public LowThreadHelp1(string name)
153
{
154
this._name = name;
155
Console.WriteLine("{1}创建新的LowLevel1Help对象:{0}", name, DateTime.Now);
156
}
157
158
//这个方法对应的是LowLevel1.FightOver2()
159
//当有线程调用LowLevel1.FightOver2()时,LowLevel1的Type对象被锁了,需要在Lock中睡5s
160
//如果在5s内有线程调用这个FightHelp2()方法时,这个线程将被阻塞,进入线程列队
161
//等到5s过后才能调用FightHelp2()中Lock里面的东西
162
public void FightHelp2()
163
{
164
lock (typeof(LowThread1))
165
{
166
Console.WriteLine("{1}执行LowLevel1Help.FightHelp2():{0}", this._name, DateTime.Now);
167
}
168
}
169
//这个方法对象的是LowLevel1.FightOver3()
170
//当有线程执行LowLevel1.FightOver2()时,执行这个方法的对象被锁了,需要在Lock中睡5s
171
//如果5s内有线程调用这个FightHelp3()方法时,这个线程将被阻塞,进入线程列队
172
//等待5s过后才能调用FightHelp3()中Lock里的东西
173
public void FightHelp3(object obj)
174
{
175
LowThread1 ll1 = (LowThread1)obj;
176
lock (ll1)
177
{
178
Console.WriteLine("{1}执行LowLevel1Help.FightHelp3()------{0}", this._name, DateTime.Now);
179
Console.WriteLine("{2}得到LowLevel1.Data:{0}------{1}", ll1.Data, this._name, DateTime.Now);
180
}
181
}
182
}
183
}
184

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30



31

32

33

34


35

36

37

38

39

40

41

42

43

44

45

46

47



48

49

50

51

52

53

54

55

56

57

58

59

60



61

62

63

64

65

66

67

68

69

70

71

72

73



74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

标签:
线程
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 周边上新:园子的第一款马克杯温暖上架