c# Semaphore 和 Mutex 的区别 c#信号量有什么用


该用 Semaphore 而非 Mutex 的核心判断是:需控制“最多 N 个线程同时执行”时选 Semaphore,需“仅一个线程进入”时才考虑 Mutex;Semaphore 是无所有权的配额计数器,Mutex 是有所有权的独占锁。

什么时候该用 Semaphore,而不是 Mutex

核心判断就一条:你要控制的是“最多 N 个线程同时干活”,还是“必须只有一个线程能进”。前者选 Semaphore,后者才考虑 Mutex(或更轻量的 lock)。

Mutex 是“独占锁”——它只认“谁拿了,谁放”,且只允许一个线程持有;Semaphore 是“配额计数器”——它不记谁拿了,只管还剩几个“入场券”。比如数据库连接池设为 10,第 11 个线程调用 WaitOne() 就得排队,不管前 10 个是谁。

  • 需要跨进程互斥(如确保程序只启动一个实例)→ 必须用命名 MutexSemaphore 不行
  • 要限制并发 HTTP 请求不超过 5 个 → 用 Semaphore(5, 5),别碰 Mutex
  • 保护一个全局 int counter 被多线程累加 → 直接用 lockInterlocked.IncrementMutex 太重,Semaphore 语义错

Semaphore 的典型用途和构造参数怎么填

Semaphore 的两个构造参数:初始可用数(initialCount)和最大容量(maximumCount),不是“当前用了几个”或“总共创建几个”,而是“一开始发几张票”和“最多能发多少张票”。

常见误写:new Semaphore(0, 10) —— 这等于开门就拒客,所有线程一来就阻塞,除非你后续主动 Release(10),否则永远卡死。

  • 资源池场景(如连接池上限 8)→ new Semaphore(8, 8):起始全空闲,最多允许 8 并发
  • 生产者-消费者缓冲区大小为 10 → 用两个信号量:emptySlots = new Semaphore(10, 10)(空位),filledItems = new Semaphore(0, 10)(已填项)
  • 限流 API 调用(每秒最多 3 次)→ 配合 Timer 或令牌桶,但底层可基于 SemaphoreSlim 实现轻量等待

SemaphoreMutex 最容易踩的坑

最危险的区别在“所有权”:Mutex 只能由获取它的线程调用 ReleaseMutex(),否则抛 ApplicationException;而 Semaphore 任意线程都能调用 Release() —— 这既是灵活性来源,也是 bug 温床。

  • 误在非持有线程释放 Mutex → 程序崩溃或静默失败(尤其在异步/线程池回调中)
  • 忘记 Release() 导致 Semaphore 一直被扣光 → 后续所有线程永久挂起,无异常提示
  • Semaphore(1, 1) 替代 Mutex → 功能看似一样,但失去所有权检查,调试时难定位谁没释放
  • 跨进程场景硬上 Semaphore → 它不支持跨进程同步,命名无效,会静默创建多个独立实例

性能与替代选择:什么时候该换 SemaphoreSlim

如果你的场景纯属进程内(in-process)、高频率争抢(比如每毫秒几十次 WaitOne),Semaphore 的内核态开销明显高于 SemaphoreSlim —— 前者每次调用都涉及系统调用,后者优先用自旋+用户态等待。

但注意:SemaphoreSlim 不支持跨进程,也不支持等待超时时指定 CancellationToken 的某些高级行为(.NET 6+ 已补全),且不能用于 WaitHandle.WaitAll() 等 WaitHandle 组合操作。

  • Web API 限流、内存缓存并发读写控制 → 优先 SemaphoreSlim
  • 需和 AutoResetEvent 等一起做 WaitHandle 数组等待 → 必须用 Semaphore
  • 日志写入器要防多进程同时写同一文件 → Mutex(命名)才是正解,SemaphoreSlim 根本无效

真正复杂的地方不在语法,而在于想清楚:你锁的到底是一个“门禁权限”,还是一批“限量门票”。混淆这两者,代码可能跑得通,但会在高并发或异常路径下突然卡死、数据错乱,而且极难复现。


# app  # ai  # 区别  # c#  # .net  # int  # 线程  # 多线程  # 并发  # 异步  # 数据库  # http  # bug  # 最多  # 几个  # 什么时候  # 拿了  # 它不  # 该用  # 的是  # 是一个  # 信号量  # 也不 


相关栏目: 【 Google疑问12 】 【 Facebook疑问10 】 【 网络优化76771 】 【 技术知识130152 】 【 IDC云计算60162 】 【 营销推广131313 】 【 AI优化88182 】 【 百度推广37138 】 【 网站推荐60173 】 【 精选阅读31334


相关推荐: C++如何解析JSON数据?(nlohmann/json库示例)  如何在Golang中写入JSON文件_保存结构体数据到文件  Laravel 查询 JSON 列:高效筛选包含数组中任意值的记录  Windows11怎么自定义任务栏_Windows11任务栏自定义教程【步骤】  php在Linux怎么部署_LNMP环境搭建PHP服务的详细指南【指南】  Mac版Final Cut Pro入门_Mac视频剪辑基础操作【教程】  Win11怎么查看wifi信号强度_检测Windows 11无线网络质量方法【详解】  c++中的可变参数模板(variadic templates)怎么用_c++模板编程黑魔法【C++11】  mac怎么看硬盘大小_MAC查看磁盘存储空间与文件占用【详解】  如何使用Golang实现基本类型比较_Golang比较操作符使用方法  c++中explicit(bool)的用法 c++条件性explicit【C++20】  Python文件和流处理指南_高效读写大体积数据文件  Win10怎样清理C盘爱奇艺缓存_Win10清理爱奇艺缓存步骤【步骤】  如何使用Golang table-driven fuzz测试_多数据随机化发现缺陷  Windows10怎么用“讲述人”读屏辅助 Windows10轻松使用开启讲述人朗读屏幕文字帮助视障用户【教程】  如何高效获取循环末次生成的 NumPy 数组最后一个元素(无需额外循环)  Flask 表单数据通过 SMTP 发送邮件的完整实现教程  Win11怎么设置单手模式_Win11触控键盘布局调整教程【技巧】  Win11怎么更改计算机名_Windows11系统信息重命名设备教程  Win11怎么把图标拖到任务栏_Win11固定应用快捷方式指南【方法】  Win11任务栏怎么放到顶部_Win11修改任务栏位置方法【详细】  如何使用Golang实现路由参数绑定_使用Mux和Request解析路径变量  php怎么操作Redis_Redis扩展连接与基本命令使用方法【方法】  如何有效拦截拼接式恶意域名的垃圾信息  手机php怎么转mp4_手机端php文件转mp4app推荐【指南】  Win11怎么更改任务栏位置_修改注册表将Win11任务栏置顶【教程】  ACF 教程:如何正确更新嵌套在多层 Group 字段内的子字段  Python高性能计算项目教程_NumPyCythonGPU并行加速  Win11怎么关闭通知中心_Windows11系统通知与专注助手设置  Windows10如何查看保存的WiFi密码_Win10命令行netsh wlan查询  如何在 Go 中调用动态链接库(.so)中的函数  Win11怎么自动隐藏任务栏_Win11全屏显示设置【美化】  如何在Golang中指定模块版本_使用go.mod控制版本号  Python包结构设计_大型项目组织解析【指导】  如何使用Golang反射将map转换为struct_Golang reflect类型映射技巧  如何使用Golang指针与接口结合_实现方法调用和动态类型  Windows10怎么查看硬件信息_Windows10硬件信息查询方法【指南】  如何使用Golang安装依赖库_管理模块和第三方包  php怎么下载安装后测试是否成功_简单脚本验证方法【操作】  如何使用Golang处理网络超时错误_Golang请求超时异常处理方法  c++中如何使用auto关键字_c++11类型推导用法说明  php485返回空数组怎么回事_php485数据接收为空排查指南【详解】  Win11如何卸载OneDrive_Win11卸载OneDrive方法【教程】  php485支持哪些操作系统_php485跨系统支持情况介绍【解答】  Win11任务栏怎么固定应用 Win11将软件图标固定到底部【步骤】  C#怎么创建控制台应用 C# Console App项目创建方法  如何在Golang中优化文件读写性能_使用缓冲和并发处理  如何使用Golang搭建本地API测试环境_快速验证接口功能  LINUX如何开放防火墙端口_Linux firewalld与iptables开放端口命令【安全配置】  PHP中require语句后直接调用返回对象方法的语法解析 

 2026-01-05

了解您产品搜索量及市场趋势,制定营销计划

同行竞争及网站分析保障您的广告效果

点击免费数据支持

提交您的需求,1小时内享受我们的专业解答。

致胜网络推广营销网


致胜网络推广营销网

致胜网络推广营销网专注海外推广十年,是谷歌推广.Facebook广告全球合作伙伴,我们精英化的技术团队为企业提供谷歌海外推广+外贸网站建设+网站维护运营+Google SEO优化+社交营销为您提供一站式海外营销服务。

 915688610

 17370845950

 915688610@qq.com

Notice

We and selected third parties use cookies or similar technologies for technical purposes and, with your consent, for other purposes as specified in the cookie policy.
You can consent to the use of such technologies by closing this notice, by interacting with any link or button outside of this notice or by continuing to browse otherwise.