SemaphoreSlim

SemaphoreSlim 是 .NET 提供的一个轻量级信号量类,用于控制对有限资源的并发访问。它是一个线程同步原语,允许指定数量的线程同时访问资源。SemaphoreSlimSemaphore 的轻量级版本,更适合在单机多线程环境中使用。
在你的代码中:
csharp复制
var semaphore = new SemaphoreSlim(10);
这行代码创建了一个 SemaphoreSlim 对象,允许最多 10 个线程 同时访问受保护的资源。

1. SemaphoreSlim 的构造函数参数

  • SemaphoreSlim(int initialCount):指定初始可用的信号量数量。
  • SemaphoreSlim(int initialCount, int maximumCount):指定初始可用的信号量数量和最大信号量数量。
在你的例子中:
csharp复制
var semaphore = new SemaphoreSlim(10);
  • 10 表示初始可用的信号量数量为 10,即最多允许 10 个线程同时访问资源。
  • 如果需要指定最大信号量数量,可以写成:
    csharp复制
    var semaphore = new SemaphoreSlim(10, 10);

2. 使用 SemaphoreSlim 的方法

2.1 WaitAsync()

WaitAsync() 方法用于请求进入信号量。如果信号量的计数大于 0,则线程进入信号量并减少计数;否则,线程将等待直到信号量可用。
csharp复制
await semaphore.WaitAsync();

2.2 Release()

Release() 方法用于释放信号量,增加信号量的计数,允许其他线程进入信号量。
csharp复制
semaphore.Release();

2.3 示例:限制并发执行

以下是一个完整的示例,展示如何使用 SemaphoreSlim 限制并发执行:
csharp复制
using System;
using System.Threading;
using System.Threading.Tasks;

class Program
{
    static async Task Main(string[] args)
    {
        var semaphore = new SemaphoreSlim(10); // 最多允许 10 个线程同时执行
        var tasks = new Task[100]; // 创建 100 个任务

        for (int i = 0; i < tasks.Length; i++)
        {
            tasks[i] = Task.Run(async () =>
            {
                await semaphore.WaitAsync(); // 请求进入信号量
                try
                {
                    Console.WriteLine($"Task {Task.CurrentId} is running.");
                    await Task.Delay(1000); // 模拟工作负载
                }
                finally
                {
                    semaphore.Release(); // 释放信号量
                }
            });
        }

        await Task.WhenAll(tasks); // 等待所有任务完成
        Console.WriteLine("All tasks completed.");
    }
}
输出示例:
复制
Task 1 is running.
Task 2 is running.
...
Task 10 is running.
Task 1 completed.
Task 11 is running.
...

3. 使用场景

SemaphoreSlim 适用于以下场景:
  1. 限制并发访问:例如,限制同时访问某个资源的线程数量。
  2. 控制线程池大小:在任务调度中,限制同时运行的任务数量。
  3. 实现资源池:例如,限制数据库连接池的大小。

4. 注意事项

  1. 异常处理:
    • try-finally 块中调用 Release(),确保即使发生异常也能正确释放信号量。
    • 如果不释放信号量,可能会导致其他线程永远等待。
  2. 性能优化:
    • SemaphoreSlim 是轻量级的,适合单机多线程环境。如果需要跨进程或跨机器同步,可以使用 Semaphore 或其他分布式锁机制。
  3. 超时机制:
    • WaitAsync() 可以设置超时时间,避免线程无限等待:
      csharp复制
      bool acquired = await semaphore.WaitAsync(TimeSpan.FromSeconds(5));
      if (!acquired)
      {
          Console.WriteLine("Timed out waiting for semaphore.");
      }

总结

SemaphoreSlim 是一个轻量级的信号量类,用于限制对有限资源的并发访问。通过 WaitAsync() 请求进入信号量,并通过 Release() 释放信号量。它适用于限制并发执行、控制线程池大小等场景。
posted @ 2025-03-10 15:03  yinghualeihenmei  阅读(150)  评论(0)    收藏  举报