SemaphoreSlim
SemaphoreSlim 是 .NET 提供的一个轻量级信号量类,用于控制对有限资源的并发访问。它是一个线程同步原语,允许指定数量的线程同时访问资源。
SemaphoreSlim
是 Semaphore
的轻量级版本,更适合在单机多线程环境中使用。在你的代码中:
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
适用于以下场景:-
限制并发访问:例如,限制同时访问某个资源的线程数量。
-
控制线程池大小:在任务调度中,限制同时运行的任务数量。
-
实现资源池:例如,限制数据库连接池的大小。
4. 注意事项
-
异常处理:
-
在
try-finally
块中调用Release()
,确保即使发生异常也能正确释放信号量。 -
如果不释放信号量,可能会导致其他线程永远等待。
-
-
性能优化:
-
SemaphoreSlim
是轻量级的,适合单机多线程环境。如果需要跨进程或跨机器同步,可以使用Semaphore
或其他分布式锁机制。
-
-
超时机制:
-
WaitAsync()
可以设置超时时间,避免线程无限等待:csharp复制bool acquired = await semaphore.WaitAsync(TimeSpan.FromSeconds(5)); if (!acquired) { Console.WriteLine("Timed out waiting for semaphore."); }
-
总结
SemaphoreSlim
是一个轻量级的信号量类,用于限制对有限资源的并发访问。通过 WaitAsync()
请求进入信号量,并通过 Release()
释放信号量。它适用于限制并发执行、控制线程池大小等场景。