SemaphoreSlim
以下示例创建一个信号量,其最大计数为三个线程,初始计数为零个线程。该示例启动了 5 个任务,所有这些任务都阻塞等待信号量。主线程调用 Release(Int32) 重载以将信号量计数增加到最大值,这允许三个任务进入信号量。每次释放信号量时,都会显示之前的信号量计数。控制台消息跟踪信号量的使用情况。每个线程的模拟工作间隔略有增加,以使输出更易于读取。
using System; using System.Threading; using System.Threading.Tasks; public class Example { private static SemaphoreSlim semaphore; // A padding interval to make the output more orderly. private static int padding; public static void Main() { // Create the semaphore. semaphore = new SemaphoreSlim(0, 3); Console.WriteLine("{0} tasks can enter the semaphore.", semaphore.CurrentCount); Task[] tasks = new Task[5]; // Create and start five numbered tasks. for (int i = 0; i <= 4; i++) { tasks[i] = Task.Run(() => { // Each task begins by requesting the semaphore. Console.WriteLine("Task {0} begins and waits for the semaphore.", Task.CurrentId); int semaphoreCount; semaphore.Wait(); try { Interlocked.Add(ref padding, 100); Console.WriteLine("Task {0} enters the semaphore.", Task.CurrentId); // The task just sleeps for 1+ seconds. Thread.Sleep(1000 + padding); } finally { semaphoreCount = semaphore.Release(); } Console.WriteLine("Task {0} releases the semaphore; previous count: {1}.", Task.CurrentId, semaphoreCount); }); } // Wait for half a second, to allow all the tasks to start and block. Thread.Sleep(500); // Restore the semaphore count to its maximum value. Console.Write("Main thread calls Release(3) --> "); semaphore.Release(3); Console.WriteLine("{0} tasks can enter the semaphore.", semaphore.CurrentCount); // Main thread waits for the tasks to complete. Task.WaitAll(tasks); Console.WriteLine("Main thread exits."); } } // The example displays output like the following: // 0 tasks can enter the semaphore. // Task 1 begins and waits for the semaphore. // Task 5 begins and waits for the semaphore. // Task 2 begins and waits for the semaphore. // Task 4 begins and waits for the semaphore. // Task 3 begins and waits for the semaphore. // Main thread calls Release(3) --> 3 tasks can enter the semaphore. // Task 4 enters the semaphore. // Task 1 enters the semaphore. // Task 3 enters the semaphore. // Task 4 releases the semaphore; previous count: 0. // Task 2 enters the semaphore. // Task 1 releases the semaphore; previous count: 0. // Task 3 releases the semaphore; previous count: 0. // Task 5 enters the semaphore. // Task 2 releases the semaphore; previous count: 1. // Task 5 releases the semaphore; previous count: 2. // Main thread exits.
信号量有两种类型:局部信号量和命名系统信号量。本地信号量是应用程序的本地信号量,系统信号量在整个操作系统中可见,适用于进程间同步。SemaphoreSlim 是不使用 Windows 内核信号量的 Semaphore 类的轻量级替代项。与 Semaphore 类不同,SemaphoreSlim 类不支持命名系统信号量。您只能将其用作本地信号量。SemaphoreSlim 类是建议用于在单个应用中进行同步的信号量。
轻量级信号量控制对应用程序本地资源池的访问。实例化信号量时,可以指定可以同时进入信号量的最大线程数。还可以指定可以同时输入信号量的初始线程数。这定义了信号量的计数。
每次线程进入信号量时,计数都会递减,每次线程释放信号量时,计数都会递增。若要输入信号量,线程将调用 Wait 或 WaitAsync 重载之一。若要释放信号量,它会调用 Release 重载之一。当计数达到零时,对其中一个方法的后续调用将阻塞,直到其他线程释放信号量。如果多个线程被阻塞,则没有保证的顺序(如 FIFO 或 LIFO)来控制线程何时进入信号量。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
2021-12-12 C# 多线程等待子线程结束 Task.Factory
2021-12-12 C# 多线程等待子线程全部完成 ThreadPool