C#线程安全

多个线程对同一资源的争夺,有可能出现线程不安全的现象。用lock这种最简单的方式实现下。

直观的看下这种情况:

1
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
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Threading;

namespace ThreadSafetyDemo
{
class Program
{
[STAThread]
static void Main()
{
Thread.CurrentThread.Name = "====主线程====";
Program prg = new Program();

Thread newThread = new Thread(new ThreadStart(prg.DoSomeWork));
newThread.Name = "**新线程:";
newThread.IsBackground = true;
newThread.Start(); // 开始新线程

prg.DoSomeWork(); // 开始主线程

Console.ReadKey();
}
// 放在外面作为成员变量,这样连个线程操纵的时候才能看出不一样。
private int counter = 0;

private void DoSomeWork()
{
for (int i = 1; i < 11; i++) {
counter += i;
Console.WriteLine("{0}{1}", Thread.CurrentThread.Name, counter);
}
}
}
}

输出:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
====主线程====1
====主线程====4
====主线程====7
====主线程====11
====主线程====16
====主线程====22
====主线程====29
**新线程:2
**新线程:39
**新线程:42
**新线程:46
**新线程:51
**新线程:57
**新线程:64
**新线程:72
**新线程:81
**新线程:91
====主线程====37
====主线程====100
====主线程====110

每次的结果其实都不一样,这就是线程的不安全,多个线程操纵了同意资源。

保证线程安全,加一个lock块。

1
2
3
4
5
6
7
8
9
private void DoSomeWork()
{
lock (this) {
for (int i = 1; i < 11; i++) {
counter += i;
Console.WriteLine("{0}{1}", Thread.CurrentThread.Name, counter);
}
}
}

这样就没问题,保证只有一个线程调用。

更优雅的方式写法:

增加命名空间using System.Runtime.CompilerServices;。然后在函数前增加一个这样的标签就可以——[MethodImpl(MethodImplOptions.Synchronized)]

1
2
3
4
5
6
7
8
9

[MethodImpl(MethodImplOptions.Synchronized)]
private void DoSomeWork()
{
for (int i = 1; i < 11; i++) {
counter += i;
Console.WriteLine("{0}{1}", Thread.CurrentThread.Name, counter);
}
}

这样子也可以,也是同样的效果。

感谢支持!