编辑
2025-09-18
C#
00

目录

SemaphoreSlim简介
SemaphoreSlim的特点
SemaphoreSlim的构造函数
SemaphoreSlim的常用方法
示例:使用SemaphoreSlim控制访问
示例1:基本用法
示例2:异步用法
总结

在多线程和并发编程中,同步机制是不可或缺的,它帮助我们控制对共享资源的访问,以及管理线程间的协作。C#提供了多种同步原语,其中SemaphoreSlim是一个轻量级的同步原语,用于控制访问有限数量的资源。本文将深入探讨SemaphoreSlim的特点、构造函数、常用方法,并通过实例来展示其用法。

SemaphoreSlim简介

SemaphoreSlim是.NET Framework中System.Threading命名空间下的一个类,它提供了一个信号量机制,允许多个线程同时访问一定数量的资源。与Semaphore类相比,SemaphoreSlim是一个更轻量级的版本,专为需要高性能的场景设计,它主要适用于任务和异步编程。

SemaphoreSlim的特点

  • 轻量级SemaphoreSlim提供了一个简单而高效的信号量机制,相较于Semaphore,它在性能上有所优化,特别是在同一进程内部使用时。
  • 灵活性:支持同步和异步的等待操作,使得它在异步编程中非常有用。
  • 限制并发访问:可以限制对共享资源或共享操作的并发访问数量,从而实现对资源的有效管理。

SemaphoreSlim的构造函数

SemaphoreSlim提供了三个构造函数:

  1. SemaphoreSlim(int initialCount):初始化SemaphoreSlim的实例,设置初始的信号量计数。
  2. SemaphoreSlim(int initialCount, int maxCount):初始化SemaphoreSlim的实例,设置初始的信号量计数和最大信号量计数。
  3. SemaphoreSlim(int initialCount, int maxCount, CancellationToken cancellationToken):此构造函数不存在。SemaphoreSlim不直接在构造函数中支持CancellationToken,但其WaitAsync方法支持。

SemaphoreSlim的常用方法

  • WaitWaitAsync:请求进入信号量,如果当前计数大于0,则进入并将计数减1;如果计数为0,则等待直到其他线程释放信号量。
  • Release:释放信号量,将计数增加指定的值。
  • Dispose:释放SemaphoreSlim使用的所有资源。

示例:使用SemaphoreSlim控制访问

示例1:基本用法

C#
using System; using System.Threading; using System.Threading.Tasks; class Program { static SemaphoreSlim semaphoreSlim = new SemaphoreSlim(3); // 最多允许3个线程同时访问 static void AccessDatabase(string name, int seconds) { Console.WriteLine($"{name} waits to access a database."); semaphoreSlim.Wait(); Console.WriteLine($"{name} is accessing the database."); Thread.Sleep(TimeSpan.FromSeconds(seconds)); // 模拟数据库访问 Console.WriteLine($"{name} is done."); semaphoreSlim.Release(); } static void Main(string[] args) { for (int i = 1; i <= 5; i++) { int id = i; Task.Run(() => AccessDatabase($"Task {id}", id)); } Console.ReadLine(); } }

image.png

这个例子创建了一个SemaphoreSlim实例,允许最多3个线程同时访问数据库。通过WaitRelease方法,我们控制了对数据库访问的并发数。

示例2:异步用法

C#
using System; using System.Threading; using System.Threading.Tasks; class Program { static SemaphoreSlim semaphoreSlim = new SemaphoreSlim(3); // 最多允许3个任务同时执行 static async Task AccessResourceAsync(string name, int seconds) { Console.WriteLine($"{name} waits to access a resource."); await semaphoreSlim.WaitAsync(); Console.WriteLine($"{name} is accessing the resource."); await Task.Delay(TimeSpan.FromSeconds(seconds)); // 模拟异步操作 Console.WriteLine($"{name} is done."); semaphoreSlim.Release(); } static async Task Main(string[] args) { Task[] tasks = new Task[5]; for (int i = 1; i <= 5; i++) { int id = i; tasks[i - 1] = AccessResourceAsync($"Task {id}", id); } await Task.WhenAll(tasks); Console.WriteLine("All tasks have been completed."); } }

image.png

在这个异步示例中,我们使用WaitAsync方法替代了Wait方法,以非阻塞的方式等待信号量。这对于异步编程场景特别有用,因为它避免了在等待时阻塞线程。

总结

SemaphoreSlim是C#中一个非常有用的同步原语,它提供了一种高效的方式来控制对共享资源的并发访问。通过上述示例,我们可以看到SemaphoreSlim在同步和异步编程中的应用。掌握SemaphoreSlim的使用,对于开发高效、可靠的多线程和异步应用程序至关重要。

本文作者:技术老小子

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!