导读:本期聚焦于小伙伴创作的《C#怎么使用异步锁SemaphoreSlim实现异步场景下的加锁方法》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《C#怎么使用异步锁SemaphoreSlim实现异步场景下的加锁方法》有用,将其分享出去将是对创作者最好的鼓励。

在C#的异步编程场景里,传统的lock关键字只能作用于同步代码块,无法在包含await的异步方法中使用,否则会直接编译报错。这时候SemaphoreSlim就成为了实现异步锁的最佳选择,它支持异步等待获取锁,完美适配异步编程模型。

C#怎么使用异步锁SemaphoreSlim实现异步场景下的加锁方法

SemaphoreSlim基础介绍

SemaphoreSlim是.NET提供的轻量级信号量实现,相比传统的Semaphore类,它没有使用Windows内核对象,性能更高,更适合进程内的线程同步场景。它的核心作用是限制同时访问某一资源或资源池的线程数量,当初始计数设置为1时,就可以实现类似互斥锁的效果,也就是我们常说的异步锁。

SemaphoreSlim常用的核心方法如下:

  • WaitAsync():异步等待获取信号量,可设置超时时间,不会阻塞当前线程
  • Release():释放信号量,增加信号量的计数,唤醒等待的线程
  • AvailableWaitHandle:获取用于等待信号量的等待句柄,一般异步场景很少使用

异步锁的基本使用步骤

使用SemaphoreSlim实现异步加锁的流程非常简单,主要分为三步:初始化信号量、异步等待获取锁、释放锁。需要注意释放锁的操作一定要放在try-finally块中,避免获取锁之后因为异常导致锁无法释放,造成死锁。

基础使用示例

下面是一个简单的异步加锁示例,模拟多个异步任务同时访问共享资源的场景:

using System;
using System.Threading;
using System.Threading.Tasks;

class Program
{
    // 初始化SemaphoreSlim,初始计数为1,最大计数也为1,实现互斥锁效果
    private static SemaphoreSlim _asyncLock = new SemaphoreSlim(1, 1);
    // 共享资源
    private static int _sharedCount = 0;

    static async Task Main(string[] args)
    {
        // 创建10个异步任务同时执行
        var tasks = new Task[10];
        for (int i = 0; i < 10; i++)
        {
            tasks[i] = AccessSharedResourceAsync(i);
        }
        await Task.WhenAll(tasks);
        Console.WriteLine($"最终共享资源值:{_sharedCount}");
    }

    static async Task AccessSharedResourceAsync(int taskId)
    {
        Console.WriteLine($"任务{taskId}开始等待获取锁");
        // 异步等待获取锁
        await _asyncLock.WaitAsync();
        try
        {
            Console.WriteLine($"任务{taskId}获取到锁,开始操作共享资源");
            // 模拟异步操作
            await Task.Delay(100);
            // 操作共享资源
            int temp = _sharedCount;
            await Task.Delay(50);
            _sharedCount = temp + 1;
            Console.WriteLine($"任务{taskId}操作完成,当前共享资源值:{_sharedCount}");
        }
        finally
        {
            // 释放锁,确保无论是否出现异常都会执行
            _asyncLock.Release();
            Console.WriteLine($"任务{taskId}释放锁");
        }
    }
}

运行上述代码可以看到,所有任务都是依次获取锁、操作资源、释放锁,不会出现多个任务同时修改共享资源的情况,最终_sharedCount的值会是10,符合预期。

带超时的异步锁使用

在实际场景中,我们可能不希望任务无限等待获取锁,这时候可以给WaitAsync方法设置超时时间,如果超过指定时间没有获取到锁,就执行其他逻辑。

using System;
using System.Threading;
using System.Threading.Tasks;

class TimeoutExample
{
    private static SemaphoreSlim _asyncLock = new SemaphoreSlim(1, 1);

    static async Task Main(string[] args)
    {
        // 先启动一个任务长期持有锁
        var holdLockTask = HoldLockLongTimeAsync();
        await Task.Delay(100);

        // 另一个任务尝试获取锁,设置500毫秒超时
        bool isLockAcquired = await _asyncLock.WaitAsync(500);
        if (isLockAcquired)
        {
            try
            {
                Console.WriteLine("成功获取到锁,执行操作");
            }
            finally
            {
                _asyncLock.Release();
            }
        }
        else
        {
            Console.WriteLine("获取锁超时,执行超时逻辑");
        }

        await holdLockTask;
    }

    static async Task HoldLockLongTimeAsync()
    {
        await _asyncLock.WaitAsync();
        try
        {
            Console.WriteLine("长期持有锁的任务开始执行");
            await Task.Delay(2000);
            Console.WriteLine("长期持有锁的任务执行完成");
        }
        finally
        {
            _asyncLock.Release();
        }
    }
}

上述代码中,第二个任务尝试获取锁时设置了500毫秒的超时,而第一个任务会持有锁2秒,因此第二个任务会获取锁失败,执行超时逻辑。

SemaphoreSlim使用注意事项

  • 一定要保证Release的调用次数和WaitAsync的调用次数匹配,否则会导致信号量计数异常,甚至引发异常。如果不确定,可以在Release时指定释放的数量,默认是释放1个。
  • SemaphoreSlim实现了IDisposable接口,如果确定不再使用,可以调用Dispose方法释放资源,不过一般进程内的同步场景不需要手动释放,进程结束会自动回收。
  • 不要尝试在SemaphoreSlim的等待过程中使用lock关键字,两者属于不同的同步机制,混合使用很容易引发死锁。
  • 如果需要在多个进程之间同步资源,SemaphoreSlim无法满足需求,需要使用传统的Semaphore类,因为它支持命名系统信号量,可以实现跨进程同步。

和普通lock的对比

为了更清晰地了解SemaphoreSlim的适用场景,我们可以把它和传统的lock关键字做对比:

对比项lock关键字SemaphoreSlim(初始计数1)
适用场景同步代码块,无await操作异步代码块,包含await操作
等待方式阻塞当前线程异步等待,不阻塞线程
超时支持不支持支持WaitAsync超时
跨进程支持不支持不支持
性能很高较高,略低于lock

通过对比可以看出,在异步场景下优先选择SemaphoreSlim实现加锁,同步场景下优先使用lock关键字,这样能获得更好的性能。

C#SemaphoreSlim异步锁异步编程线程同步修改时间:2026-06-27 19:51:33

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。