当前位置:首页 > C# > 正文

C#中的Semaphore信号量详解(手把手教你用信号量限制并发数)

在多线程编程中,我们常常需要控制同时访问某个资源的线程数量。比如:限制数据库连接池的最大连接数、限制同时下载文件的数量等。这时候,C# Semaphore(信号量)就派上用场了!本文将带你从零开始理解并使用信号量限制并发数,即使是编程小白也能轻松掌握。

C#中的Semaphore信号量详解(手把手教你用信号量限制并发数) C# Semaphore 信号量限制并发数 C#并发控制 SemaphoreSlim教程 第1张

什么是Semaphore?

Semaphore(信号量)是一种用于控制多个线程对共享资源进行访问的同步原语。你可以把它想象成一个“许可证发放机”:它最多可以发放 N 个许可证,当有线程想进入临界区时,必须先申请一个许可证;如果许可证已全部发放完,线程就必须等待,直到有其他线程释放许可证。

在 C# 中,有两个常用的信号量类:

  • Semaphore:基于 Windows 内核对象,可用于跨进程同步。
  • SemaphoreSlim:轻量级实现,仅用于单进程内的线程同步,性能更好,推荐日常使用。

使用 SemaphoreSlim 限制并发数

下面我们通过一个实际例子来演示如何使用 SemaphoreSlim 来限制最多只有 3 个线程同时执行某项任务。

using System;using System.Threading;using System.Threading.Tasks;class Program{    // 创建一个信号量,初始可用许可证数为 3,最大也是 3    private static readonly SemaphoreSlim _semaphore = new SemaphoreSlim(3, 3);    static async Task Main(string[] args)    {        // 启动 10 个并发任务        var tasks = new Task[10];        for (int i = 0; i < 10; i++)        {            int taskId = i; // 避免闭包问题            tasks[i] = Task.Run(async () =>            {                await _semaphore.WaitAsync(); // 申请许可证                try                {                    Console.WriteLine($"任务 {taskId} 开始执行,当前时间:{DateTime.Now:HH:mm:ss}");                    await Task.Delay(2000); // 模拟耗时操作                    Console.WriteLine($"任务 {taskId} 执行完毕");                }                finally                {                    _semaphore.Release(); // 释放许可证                }            });        }        await Task.WhenAll(tasks);        Console.WriteLine("所有任务已完成!");    }}

在这个例子中:

  • 我们创建了一个 SemaphoreSlim(3, 3),表示最多允许 3 个线程同时进入临界区。
  • 每个任务在执行前调用 WaitAsync() 获取许可证,执行完成后在 finally 块中调用 Release() 释放许可证,确保即使发生异常也能正确释放。
  • 运行结果会显示:虽然启动了 10 个任务,但任意时刻最多只有 3 个任务在“执行中”,完美实现了 C#并发控制

关键注意事项

  1. 必须配对使用:每次 WaitWaitAsync 都必须对应一次 Release,否则会导致信号量计数错误,进而引发死锁或资源泄漏。
  2. 异常安全:务必在 try-finally 块中释放信号量,这是保证线程安全的关键。
  3. 选择合适的类型:如果是单进程内使用,优先选择 SemaphoreSlim,它更轻量、性能更高;如果需要跨进程同步,才考虑 Semaphore

总结

通过本文,你已经掌握了如何使用 SemaphoreSlim 教程 中的核心技巧来限制并发线程数。无论是处理高并发请求、控制资源访问,还是优化系统性能,C# Semaphore 都是一个强大而实用的工具。

记住:合理使用信号量,不仅能提升程序稳定性,还能有效防止资源过载。赶快在你的项目中试试吧!