转:线程基础示例代码之Semaphore 和 SemaphoreSlim

Semaphore表示一个命名(系统范围内)或本地信号量。它是对 Win32 信号量对象的封装,Win32 信号量是计数信号量,其可用于控制对资源池的访问。而 SemaphoreSlim 类为一个轻量、快速的信号量,可在等待时间预计很短的情况下,用于在单个进程内的等待

信号量可用于生产者、消费者线程,其中一个线程始终增加信号量计数,另一个始终减少信号量计数

示例代码如下,举一个食堂吃饭的例子

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Threading;
 4 using System.Threading.Tasks;
 5 
 6 public class App {
 7     static void Main(string[] args) {
 8         // 假设共有 10 个学生
 9         int studentCount = 10;
10         // 食堂里面共有 4 个位置
11         int seatCount = 4;
12         var semaphore = new SemaphoreSlim(seatCount, seatCount);
13         var eatings = new List<Task>();
14         for (int i = 0; i < studentCount; i++) {
15             eatings.Add(Task.Run(() => Eat(semaphore)));
16         }
17         Task.WaitAll(eatings.ToArray());
18     }
19     static void Eat(SemaphoreSlim semaphore) {
20         // 排队中,即等待有空位置出来
21         semaphore.Wait();
22         try {
23             // 有一个空位,因此可以坐下吃饭了
24             Console.WriteLine("{0}占了一个位置,准备坐下吃饭了", Task.CurrentId);
25             Thread.Sleep(1000);
26         } finally {
27             Console.WriteLine("{0} 已经吃完了,准备让出位置", Task.CurrentId);
28             // 将位置让出来
29             semaphore.Release();
30         }
31     }
32 }

 运行结果如下

 1 1占了一个位置,准备坐下吃饭了
 2 3占了一个位置,准备坐下吃饭了
 3 2占了一个位置,准备坐下吃饭了
 4 4占了一个位置,准备坐下吃饭了
 5 4 已经吃完了,准备让出位置
 6 5占了一个位置,准备坐下吃饭了
 7 3 已经吃完了,准备让出位置
 8 6占了一个位置,准备坐下吃饭了
 9 2 已经吃完了,准备让出位置
10 1 已经吃完了,准备让出位置
11 8占了一个位置,准备坐下吃饭了
12 7占了一个位置,准备坐下吃饭了
13 5 已经吃完了,准备让出位置
14 9占了一个位置,准备坐下吃饭了
15 8 已经吃完了,准备让出位置
16 10占了一个位置,准备坐下吃饭了
17 6 已经吃完了,准备让出位置
18 7 已经吃完了,准备让出位置
19 9 已经吃完了,准备让出位置
20 10 已经吃完了,准备让出位置

 相信这个例子可以使我们理解得更加深刻

而对于命名信号量,我们只需要在使用时,按以下方式即可

需要注意的是,SemaphoreSlim 不支持命名信号量

1 Semaphore semaphore = new Semaphore(4, 4, "Named_Semaphore");

转自链接:https://www.jianshu.com/p/a9d16eecee98

posted @ 2020-02-19 18:46  Jearay  阅读(357)  评论(0编辑  收藏  举报