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)来控制线程何时进入信号量。

posted @   JohnnyLei  阅读(20)  评论(0编辑  收藏  举报
(评论功能已被禁用)
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
历史上的今天:
2021-12-12 C# 多线程等待子线程结束 Task.Factory
2021-12-12 C# 多线程等待子线程全部完成 ThreadPool
点击右上角即可分享
微信分享提示