SemaphoreSlim多线程同步
title: SemaphoreSlim
description:
published: true
date: 2024-11-09T05:40:09.467Z
tags:
editor: markdown
dateCreated: 2024-11-09T05:40:09.467Z
SemaphoreSlim 是对可同时访问某一共享资源,或资源池的线程数加以限制的 Semaphore 的轻量替代,相较于线程锁的使一块代码只能一个线程访问,SemaphoreSlim 则是让同一块代码让多个线程同时访问,并且总数量可控。
创建 SemaphoreSlim
实例
// 创建一个初始计数为2的 SemaphoreSlim 实例,最大计数为4
SemaphoreSlim semaphore = new SemaphoreSlim(initialCount: 2, maxCount: 4);
等待信号
// 同步等待信号
semaphore.Wait();
// 异步等待信号
await semaphore.WaitAsync();
释放信号
// 释放一个信号
semaphore.Release();
// 释放两个信号
semaphore.Release(2);
示例:控制并发任务数
using System;
using System.Threading;
using System.Threading.Tasks;
class Program
{
private static SemaphoreSlim semaphore = new SemaphoreSlim(1, 1);
static async Task Main(string[] args)
{
var tasks = new Task[5];
for (int i = 0; i < tasks.Length; i++)
{
var t = AccessResourceAsync(i);
tasks[i] = t;
}
await Task.WhenAll(tasks);
}
private static async Task AccessResourceAsync(int id)
{
await semaphore.WaitAsync();
try
{
Console.WriteLine($"Task {id} is accessing the resource.");
await Task.Delay(1000); // 模拟对资源的访问
Console.WriteLine($"Task {id} has finished accessing the resource.");
}
finally
{
semaphore.Release();
}
}
}
Task.WhenAll(tasks) 中的 task 是同时执行,执行顺序不一定。输出结果:
Task 0 is accessing the resource.
Task 0 has finished accessing the resource.
Task 1 is accessing the resource.
Task 1 has finished accessing the resource.
Task 2 is accessing the resource.
Task 2 has finished accessing the resource.
Task 4 is accessing the resource.
Task 4 has finished accessing the resource.
Task 3 is accessing the resource.
Task 3 has finished accessing the resource.
改成最多允许两个线程同时访问:
private static SemaphoreSlim semaphore = new SemaphoreSlim(1, 1);
输出:
Task 0 is accessing the resource.
Task 2 is accessing the resource.
Task 0 has finished accessing the resource.
Task 2 has finished accessing the resource.
Task 1 is accessing the resource.
Task 3 is accessing the resource.
Task 3 has finished accessing the resource.
Task 1 has finished accessing the resource.
Task 4 is accessing the resource.
Task 4 has finished accessing the resource.
若初始信号量为 0,则需要手动释放(Release())信号量。Release(Int32) 可释放多个信号。
属性 CurrentCount,指的是对于 SemaphoreSlim 对象,可以输入信号量的剩余线程数。