当前位置: 首页 > news >正文

.NET 中的轻量级线程安全

对线程安全有要求的代码中,通常会使用锁(lock)。自 .NET 诞生以来就有锁,然而从 .NET Framework 4.0 开始,又诞生了 6 个轻量级的线程安全方案:SpinLock, SpinWait, CountdownEvent, SemaphoreSlim, ManualResetEventSlim, Barrier


SpinLock, SpinWait

SpinLock 被称之为“自旋锁”,SpinWait 称为“自旋等待”,适合在非常轻量的计算中使用。它与普通 lock 的区别在于普通 lock 使用 Win32 内核态对象来实现等待,Overview of Synchronization Primitives 中描述为:

you can use synchronization primitives that provide fast performance by avoiding expensive reliance on Win32 kernel objects such as wait handles whenever possible.

在这个过程中,调用线程会挂起,并造成线程的上下文切换,而这是一部分不算小的开销。

自旋等待则是继续让 CPU 执行此线程,直到锁释放。在这个过程中,此线程会持续占用 CPU 资源,但避免了线程上下文切换。所以,对于短时间的计算采用 SpinLock 实现线程安全会更加高效;而长时间的任务执行会导致占用 CPU 资源从而导致其他任务执行所需的资源减少。

CountdownEvent

并行执行一些任务之后,通常还会继续执行一些代码。初始化时设置信号量次数,随后在每一个子任务结束之后设置一个信号量(调用其 Signal 方法)可以使计数减 1.这样,在调用 Wait 等待的地方就会等计数为 0 后继续执行。

SemaphoreSlim, ManualResetEventSlim

SemaphoreSlimManualResetEventSlim 是此前 SemaphoreManualResetEvent 的轻量级版本,从其名字“slim”便能看出来。

如何轻量

这些轻量级线程同步方案因为没有使用到 Win32 内核对象,而是在 .NET 内部完成,所以只能进行线程之间的同步,不能进行跨进程同步。如果要完成跨进程的同步,需要使用 MonitorMutex 这样的方案。


参考资料

  • Overview of Synchronization Primitives - Microsoft Docs
  • Thread-Safe Collections - Microsoft Docs
  • .net 4.0新特性-自旋锁(SpinLock) - CSDN博客
  • .net 4.0新特性-CountDownEvent - CSDN博客
  • Atomicity, volatility and immutability are different, part three – Fabulous Adventures In Coding
  • How to: Enable Thread-Tracking Mode in SpinLock - Microsoft Docs
  • C# SpinWait 实现 - 程序园
  • C#并行编程 (Barrier,CountdownEvent,ManualResetEventSlim,SemaphoreSlim,SpinLock,SpinWait )–Thread,Ant,ICP,index,ConsoleWriteLine,CookTasks,cook,particpants

相关文章:

  • 将 WPF、UWP 以及其他各种类型的旧样式的 csproj 文件迁移成新样式的 csproj 文件
  • .NET Core 和 .NET Framework 中的 MEF2
  • 推荐近乎免费的调试神器——OzCode
  • 再也不用克隆多个仓库啦!git worktree 一个 git 仓库可以连接多个工作目录
  • 让一个 csproj 项目指定多个开发框架
  • 在操作系统重启后恢复应用程序的工作状态
  • 生成代码,从 T 到 T1, T2, Tn —— 自动生成多个类型的泛型
  • 应该抛出什么异常?不应该抛出什么异常?(.NET/C#)
  • 关闭模态窗口后,父窗口居然跑到了其他窗口的后面
  • 语义耦合(Semantic Coupling)
  • .NET Core/Framework 创建委托以大幅度提高反射调用的性能
  • 在 Windows 安装期间将 MBR 磁盘转换为 GPT 磁盘
  • 解决大于 4GB 的 Windows 10 镜像在 UEFI 模式下的安装问题
  • 为什么 UEFI 方式启动的 U 盘必须使用 FAT32 文件系统?
  • 不再为命名而苦恼!使用 MSTestEnhancer 单元测试扩展,写契约就够了
  • [Vue CLI 3] 配置解析之 css.extract
  • “Material Design”设计规范在 ComponentOne For WinForm 的全新尝试!
  • android 一些 utils
  • JavaScript 基础知识 - 入门篇(一)
  • spring boot下thymeleaf全局静态变量配置
  • 构造函数(constructor)与原型链(prototype)关系
  • 回顾2016
  • 极限编程 (Extreme Programming) - 发布计划 (Release Planning)
  • 精益 React 学习指南 (Lean React)- 1.5 React 与 DOM
  • 小而合理的前端理论:rscss和rsjs
  • 06-01 点餐小程序前台界面搭建
  • Salesforce和SAP Netweaver里数据库表的元数据设计
  • 阿里云重庆大学大数据训练营落地分享
  • $().each和$.each的区别
  • (13):Silverlight 2 数据与通信之WebRequest
  • (ibm)Java 语言的 XPath API
  • (Java)【深基9.例1】选举学生会
  • (附源码)基于SpringBoot和Vue的厨到家服务平台的设计与实现 毕业设计 063133
  • (理论篇)httpmoudle和httphandler一览
  • (算法)前K大的和
  • (转载)利用webkit抓取动态网页和链接
  • *p++,*(p++),*++p,(*p)++区别?
  • ./configure,make,make install的作用(转)
  • .aanva
  • .NET Core MongoDB数据仓储和工作单元模式封装
  • .NET 使用 XPath 来读写 XML 文件
  • .net 提取注释生成API文档 帮助文档
  • .net6Api后台+uniapp导出Excel
  • .Net8 Blazor 尝鲜
  • .netcore如何运行环境安装到Linux服务器
  • .NET成年了,然后呢?
  • .net对接阿里云CSB服务
  • .NET平台开源项目速览(15)文档数据库RavenDB-介绍与初体验
  • .pub是什么文件_Rust 模块和文件 - 「译」
  • [ IOS ] iOS-控制器View的创建和生命周期
  • [ JavaScript ] JSON方法
  • [ vulhub漏洞复现篇 ] Grafana任意文件读取漏洞CVE-2021-43798
  • [20190401]关于semtimedop函数调用.txt
  • [AI]ChatGPT4 与 ChatGPT3.5 区别有多大
  • [Android Pro] listView和GridView的item设置的高度和宽度不起作用