在.NET中要实现线程安全,可有多种途径:
1. 使用 lock 关键字:
1 using System;
2 using System.Threading;
3
4 namespace UDNZ.SynTest
5 {
6 class Program
7 {
8 static int _x = 0;
9 static int _n = 1000000;
10 static object _lock = new object();
11
12 static void Main(string[] args)
13 {
14 EventWaitHandle w1 = new EventWaitHandle(false, EventResetMode.AutoReset);
15 EventWaitHandle w2 = new EventWaitHandle(false, EventResetMode.AutoReset);
16 EventWaitHandle w3 = new EventWaitHandle(false, EventResetMode.AutoReset);
17 EventWaitHandle w4 = new EventWaitHandle(false, EventResetMode.AutoReset);
18
19 while (true)
20 {
21 _x = 0;
22 new Thread((ThreadStart)delegate { SynTest(); w1.Set(); }).Start();
23 new Thread((ThreadStart)delegate { SynTest(); w2.Set(); }).Start();
24 new Thread((ThreadStart)delegate { SynTest(); w3.Set(); }).Start();
25 new Thread((ThreadStart)delegate { SynTest(); w4.Set(); }).Start();
26
27 EventWaitHandle.WaitAll(new WaitHandle[] { w1, w2, w3, w4 });
28 Console.WriteLine(_x.ToString());
29 Thread.Sleep(1000);
30 }
31 }
32
33 static void SynTest()
34 {
35 lock (_lock)
36 {
37 for (int i = 0;i < _n;i++)
38 {
39 _x++;
40 }
41 }
42 }
43 }
44 }
2 using System.Threading;
3
4 namespace UDNZ.SynTest
5 {
6 class Program
7 {
8 static int _x = 0;
9 static int _n = 1000000;
10 static object _lock = new object();
11
12 static void Main(string[] args)
13 {
14 EventWaitHandle w1 = new EventWaitHandle(false, EventResetMode.AutoReset);
15 EventWaitHandle w2 = new EventWaitHandle(false, EventResetMode.AutoReset);
16 EventWaitHandle w3 = new EventWaitHandle(false, EventResetMode.AutoReset);
17 EventWaitHandle w4 = new EventWaitHandle(false, EventResetMode.AutoReset);
18
19 while (true)
20 {
21 _x = 0;
22 new Thread((ThreadStart)delegate { SynTest(); w1.Set(); }).Start();
23 new Thread((ThreadStart)delegate { SynTest(); w2.Set(); }).Start();
24 new Thread((ThreadStart)delegate { SynTest(); w3.Set(); }).Start();
25 new Thread((ThreadStart)delegate { SynTest(); w4.Set(); }).Start();
26
27 EventWaitHandle.WaitAll(new WaitHandle[] { w1, w2, w3, w4 });
28 Console.WriteLine(_x.ToString());
29 Thread.Sleep(1000);
30 }
31 }
32
33 static void SynTest()
34 {
35 lock (_lock)
36 {
37 for (int i = 0;i < _n;i++)
38 {
39 _x++;
40 }
41 }
42 }
43 }
44 }
2. 使用 MethodImplOptions.Synchronized。
1 using System;
2 using System.Threading;
3 using System.Runtime.CompilerServices;
4
5 namespace UDNZ.SynTest
6 {
7 class Program
8 {
9 static int _x = 0;
10 static int _n = 1000000;
11
12 static void Main(string[] args)
13 {
14 EventWaitHandle w1 = new EventWaitHandle(false, EventResetMode.AutoReset);
15 EventWaitHandle w2 = new EventWaitHandle(false, EventResetMode.AutoReset);
16 EventWaitHandle w3 = new EventWaitHandle(false, EventResetMode.AutoReset);
17 EventWaitHandle w4 = new EventWaitHandle(false, EventResetMode.AutoReset);
18
19 while (true)
20 {
21 _x = 0;
22 new Thread((ThreadStart)delegate { SynTest(); w1.Set(); }).Start();
23 new Thread((ThreadStart)delegate { SynTest(); w2.Set(); }).Start();
24 new Thread((ThreadStart)delegate { SynTest(); w3.Set(); }).Start();
25 new Thread((ThreadStart)delegate { SynTest(); w4.Set(); }).Start();
26
27 EventWaitHandle.WaitAll(new WaitHandle[] { w1, w2, w3, w4 });
28 Console.WriteLine(_x.ToString());
29 Thread.Sleep(1000);
30 }
31 }
32
33 [MethodImpl(MethodImplOptions.Synchronized)]
34 static void SynTest()
35 {
36 for (int i = 0;i < _n;i++)
37 {
38 _x++;
39 }
40 }
41 }
42 }
2 using System.Threading;
3 using System.Runtime.CompilerServices;
4
5 namespace UDNZ.SynTest
6 {
7 class Program
8 {
9 static int _x = 0;
10 static int _n = 1000000;
11
12 static void Main(string[] args)
13 {
14 EventWaitHandle w1 = new EventWaitHandle(false, EventResetMode.AutoReset);
15 EventWaitHandle w2 = new EventWaitHandle(false, EventResetMode.AutoReset);
16 EventWaitHandle w3 = new EventWaitHandle(false, EventResetMode.AutoReset);
17 EventWaitHandle w4 = new EventWaitHandle(false, EventResetMode.AutoReset);
18
19 while (true)
20 {
21 _x = 0;
22 new Thread((ThreadStart)delegate { SynTest(); w1.Set(); }).Start();
23 new Thread((ThreadStart)delegate { SynTest(); w2.Set(); }).Start();
24 new Thread((ThreadStart)delegate { SynTest(); w3.Set(); }).Start();
25 new Thread((ThreadStart)delegate { SynTest(); w4.Set(); }).Start();
26
27 EventWaitHandle.WaitAll(new WaitHandle[] { w1, w2, w3, w4 });
28 Console.WriteLine(_x.ToString());
29 Thread.Sleep(1000);
30 }
31 }
32
33 [MethodImpl(MethodImplOptions.Synchronized)]
34 static void SynTest()
35 {
36 for (int i = 0;i < _n;i++)
37 {
38 _x++;
39 }
40 }
41 }
42 }
3. 使用 System.Threading.Mutex 或 System.Threading.Monitor (略)
4. 若需要Queue、Dictionary等保证线程安全,可以这样使用:
1 using System.Collections;
2 using System.Collections.Concurrent;
3
4 namespace UDNZ.SynTest
5 {
6 class Program
7 {
8 static void Main(string[] args)
9 {
10 // ...
11 Queue unsafeQ = new Queue();
12 Queue safeQ = Queue.Synchronized(unsafeQ);
13
14 Stack unsafeS = new Stack();
15 Stack safeS = Stack.Synchronized(unsafeS);
16
17 ConcurrentQueue<string> concQ = new ConcurrentQueue<string>();
18 ConcurrentBag<string> concB = new ConcurrentBag<string>();
19 ConcurrentDictionary<int, string> concD = new ConcurrentDictionary<int, string>();
20 ConcurrentStack<string> concS = new ConcurrentStack<string>();
21 // ...
22 }
23 }
24 }
2 using System.Collections.Concurrent;
3
4 namespace UDNZ.SynTest
5 {
6 class Program
7 {
8 static void Main(string[] args)
9 {
10 // ...
11 Queue unsafeQ = new Queue();
12 Queue safeQ = Queue.Synchronized(unsafeQ);
13
14 Stack unsafeS = new Stack();
15 Stack safeS = Stack.Synchronized(unsafeS);
16
17 ConcurrentQueue<string> concQ = new ConcurrentQueue<string>();
18 ConcurrentBag<string> concB = new ConcurrentBag<string>();
19 ConcurrentDictionary<int, string> concD = new ConcurrentDictionary<int, string>();
20 ConcurrentStack<string> concS = new ConcurrentStack<string>();
21 // ...
22 }
23 }
24 }