You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ASP.NET Core异步方法非可重入:lock与SemaphoreSlim选型指南

异步方法防并发:lock 和 SemaphoreSlim 怎么选?

lock 是什么情况?

  • lock是同步场景里的老伙计,基于Monitor实现,只能用在纯同步代码里。
  • 要是你在async方法里用lock包着带await的代码,编译器直接给你报错——因为lock要求拿锁的线程必须从头到尾扛到释放锁,可await会让线程跑走,锁就没人管了,肯定出问题。
  • 只有当你的RunAsync里全是同步逻辑、半点儿await都没有的时候,lock才有用武之地。

SemaphoreSlim 为啥更适合异步场景?

  • SemaphoreSlim是轻量级信号量,专门支持异步等待(靠WaitAsync()方法),天生适配async方法。
  • 把它的初始计数设为1,就能实现和锁一样的互斥效果,代码大概是这样:
    private readonly SemaphoreSlim _mutex = new SemaphoreSlim(1, 1);
    
    public async Task RunAsync()
    {
        await _mutex.WaitAsync();
        try
        {
            // 这里写你的异步业务逻辑
        }
        finally
        {
            _mutex.Release();
        }
    }
    
  • 好处是await的时候会释放当前线程,不会占着线程池资源不放,ASP.NET Core这种靠线程池吃饭的环境里,能避免不必要的线程阻塞,提升整体并发能力。
  • 一定要记得在finally里调用Release(),哪怕代码抛异常,也能保证信号量被释放,不然就会出现死锁,后面的请求永远拿不到信号量。

你的方法是async,这事儿影响大吗?

  • 太影响了!这直接把lock给pass了——lock和await根本不兼容,硬用要么编译不过,要么暗地里搞出锁泄漏、死锁的烂摊子。
  • 异步方法的核心就是线程会在await的时候切换,SemaphoreSlim的异步等待刚好能跟上这个节奏,不会像lock那样卡死线程,所以是异步场景下的唯一靠谱选择。

最后给个准话

  • 如果你的RunAsync里有await异步操作,直接用SemaphoreSlim,别想lock的事儿。
  • 只有当方法全是同步代码,半点儿异步都没有,再考虑lock。

内容的提问来源于stack exchange,提问作者Jonathan Wood

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 20:12:44