.Net并行编程(3)线程安全与同步机制(锁、信号量)

序言

1.Lock(属于Monitor的语法糖)

lock 关键字是 C# 中最简单和最常用的锁机制,用于在代码块中获取对象的互斥锁,确保同一时间只有一个线程能够执行该代码块。

https://sharplab.io/

2.Monitor

Monitor 类提供了一种更灵活的同步机制,通过 Monitor.Enter 和 Monitor.Exit 方法来获取和释放对象的锁。除了基本的互斥锁外,Monitor 还提供了等待和通知的功能,可以实现更复杂的线程同步方案。

3.Mutex

Mutex 是一种操作系统级别的内核对象,可以用于进程间的同步。在 C# 中,Mutex 类封装了操作系统提供的互斥体,可以用于实现跨进程的线程同步。

4.Semaphore

 

5.AutoResetEvent和ManualResetEvent

 

6.ReaderWriterLockSlim

基本规则: 读读不互斥 读写互斥 写写互斥

 

7.Barrier(屏障同步)

 

8.spinLock(自旋锁)

我们初识多线程或者多任务时,第一个想到的同步方法就是使用lock或者Monitor,然而在4.0 之后给我们提供了另一把武器spinLock,

如果你的任务持有锁的时间非常短,具体短到什么时候msdn也没有给我们具体的答案,但是有一点值得确定的时,如果持有锁的时候比较

短,那么它比那些重量级别的Monitor具有更小的性能开销,它的用法跟Monitor很相似,

信号量

当出现了并行计算的时候,轻量级别的同步机制应运而生,在信号量这一块出现了一系列的轻量级,今天继续介绍下面的3个信号量 CountdownEvent,SemaphoreSlim,ManualResetEventSlim。

1.CountdownEvent

  虽然通过Task.WaitAll()方法也可以达到线程同步的目的。

  但是CountdownEvent更牛X之处在于我们可以动态的改变“信号计数”的大小,比如一会儿能够容纳8个线程,一下又4个,一下又10个,CountdownEvent给我们提供了可以动态修改的解决方案。

模拟建房子工序

 1   public partial class Form1 : Form
 2     {
 3         public Form1()
 4         {
 5             InitializeComponent();
 6         }
 7 
 8         static CountdownEvent cde = null;
 9         private void button1_Click(object sender, EventArgs e)
10         {
11             //建房子第一期工人
12             string[] _bhPerson1 = new string[5] { "Yan", "Zhi", "wei", "Do", "Work" };
13             //建房子第二期工人
14             string[] _bhPerson2 = new string[3] { "Yan2", "Zhi2", "wei2" };
15             //建房子第三期工人
16             string[] _bhPerson3 = new string[3] { "Yan3", "Zhi3", "wei3" };
17             using (cde = new CountdownEvent(Environment.ProcessorCount))//开始监管,相当于监工
18             {
19                 cde.Reset(_bhPerson1.Length);//设置第一期建造需要5个人
20                 foreach (string person in _bhPerson1)
21                 {
22                     Task.Factory.StartNew(() =>
23                     {
24                         BuilderHourseStep1(person);
25                     });
26 
27                 }
28                 cde.Wait();//等待第一期建造完成
29                 Console.WriteLine("-----------------------");
30 
31                 cde.Reset(_bhPerson2.Length);//设置第二期建需要三个人
32                 foreach (string person in _bhPerson2)
33                 {
34                     Task.Factory.StartNew(() =>
35                     {
36                         BuilderHourseStep2(person);
37                     });
38                 }
39                 cde.Wait();//等待第二期建造完成
40                 Console.WriteLine("-----------------------");
41 
42                 cde.Reset(_bhPerson3.Length);//设置第三期建需要三个人
43                 foreach (string person in _bhPerson3)
44                 {
45                     Task.Factory.StartNew(() =>
46                     {
47                         BuilderHourseStep3(person);
48                     });
49                 }
50                 cde.Wait();//等待第三期建造完成
51                 Console.WriteLine("-----------------------");
52             }
53         }
54         /// <summary>
55         /// 建房子第一道所需要的工序
56         /// </summary>
57         /// <param name="person"></param>
58         static void BuilderHourseStep1(string person)
59         {
60             try
61             {
62                 Console.WriteLine(string.Format("『{0}』BuilderHourseStep1....", person));
63             }
64             finally
65             {
66                 cde.Signal();//建造完成一点后,通知监工
67             }
68         }
69         /// <summary>
70         /// 建房子第二道所需要的工序
71         /// </summary>
72         /// <param name="person"></param>
73         static void BuilderHourseStep2(string person)
74         {
75             try
76             {
77                 Console.WriteLine(string.Format("『{0}』BuilderHourseStep2.....", person));
78             }
79             finally
80             {
81                 cde.Signal();
82             }
83         }
84         /// <summary>
85         /// 建房子第三道所需要的工序
86         /// </summary>
87         /// <param name="person"></param>
88         static void BuilderHourseStep3(string person)
89         {
90             try
91             {
92                 Console.WriteLine(string.Format("『{0}』BuilderHourseStep3.......", person));
93             }
94             finally
95             {
96                 cde.Signal();
97             }
98         }
99     }
View Code

 分步执行任务

 1  static void Main(string[] args)
 2         {
 3             IList<string> taskList =new List<string> {"任务一","任务二", "任务四", "任务五", "任务六" };
 4             int count = taskList.Count;
 5             using (CountdownEvent cde = new CountdownEvent(Environment.ProcessorCount))
 6             {
 7                 cde.Reset(count);//设置信号数
 8                 foreach (var item in taskList)
 9                 {
10                     Task.Factory.StartNew(() =>
11                     {
12                         Console.WriteLine("处理任务:"+item);
13                         cde.Signal();//每次调用 Signal 时,信号计数都会递减 1。
14                     });
15                 }
16                 cde.Wait();// 在主线程上,对 Wait 的调用将会阻塞,直至信号计数为零。 
17                 Console.WriteLine("接下来开始做下一件事情");
18                 cde.Reset(count);//重置信号数
19                 foreach (var item in taskList)
20                 {
21                     Task.Factory.StartNew(() =>
22                     {
23                         Console.WriteLine("继续处理任务:" + item);
24                          cde.Signal();//每次调用 Signal 时,信号计数都会递减 1。
25                     });
26                 }
27             }
28             Console.ReadKey();
29         }
View Code

2.SemaphoreSlim

 

3.ManualResetEventSlim

 

线程安全的集合

ConcurrentBag 

BlockingCollection 

ConcurrentDictionary

ConcurrentQueue

ConcurrentStack 

资料

https://www.bilibili.com/video/BV1Cw411A7Fr/?spm_id_from=333.788&vd_source=a56db24cb8cab4dd8153f9a519787c89

https://sharplab.io/

https://www.cnblogs.com/huangxincheng/archive/2012/04/07/2437110.html

http://blog.gkarch.com/threading/part5.html#the-parallel-class

http://www.cnblogs.com/huangxincheng/archive/2012/04/08/2437701.html

http://www.cnblogs.com/yaopengfei/p/8315212.html

  

posted @ 2016-07-19 21:18  ~沐风  阅读(334)  评论(0编辑  收藏  举报