一起谈.NET技术,【经验总结】C#常用线程同步方法应用场景和实现原理

简介:   简单描述volatile,Interlocked,lock,Mutex,Semaphore,Spin lock,AutoResetEvent,ManualResetEvent,ReaderWriterLockSlim,MethodImplAttribute,WaitHandle常用同步机制的原理和使用场景。

  简单描述volatile,Interlocked,lock,Mutex,Semaphore,Spin lock,AutoResetEvent,ManualResetEvent,ReaderWriterLockSlim,MethodImplAttribute,WaitHandle常用同步机制的原理和使用场景。

  volatile

  只是C#的一个关键字,告诉编译器不能将声明的这个变量进行CPU内部缓存,只能在主内存中操作,类型有限制,volatile并不能实现真正的同步,因为它的操作级别只停留在变量级别,而不是原子级别。如果是在单处理器系统中,是没有任何问题的,变量在主存中没有机会被其他人修改,因为只有一个处理器,这就叫作processor Self-Consistency。但在多处理器系统中,可能就会有问题。 每个处理器都有自己的data cache,而且被更新的数据也不一定会立即写回到主存。所以可能会造成不同步,但这种情况很难发生,因为cache的读写速度相当快,flush的频率也相当高,只有在压力测试的时候才有可能发生,而且几率非常非常小。本质上说并非绝对的同步方法。

  Interlocked

  对于例如int变量等的原子操作,效率高,可靠性高,一般通过CPU的专用指令实现的锁住内存总线实现的。

  lock

  lock与Monitor本身是一致的,lock是做到了C#的关键字一级,是.net对象自身支持的的一种同步机制,对象中有相关的结构支持这种轻量级的线程同步,实现机制类似于CRITICAL_SECTION,但是CRITICAL_SECTION具有跨进程特性,而lock只能实现同一进程中的线程同步,在C#开发中很常用。

  Mutex

  是WIN32下的突变体内核对象的封装,类似于一间屋子只能进入一个人。是它的一个.net封装,效率比较低,由于突变体是一种windows内核对象,需要开销很大,但是支持跨进程,通过给Mutex命名的方式支持进程间同步,甚至可以跨服务器访问,是一种服务器之间同步的选择。Mutex的拥有者才能释放这个Mutex,其他进程不能释放,可能是考虑到安全问题。Mutex是一种基于线程调度的同步方式,控制的是线程的调度,实现了sleep,如果有信号可以通知内核线程调度程序调度等待线程。

  Semaphore(Binary semaphore)

  基于WIN32的Semaphore,也是一种基于线程调度,基本很类似于Mutex,与Mutex不同之处在于Semaphore允许多人进入同一间屋子,使用count计数来实现,当允许数量为1时叫做Binary semaphore,这时候就是基本和Mutex很类似的,但是没有Mutex拥有者一说,可由任何进程进行资源释放。

  Spin lock

  这是一个内核态概念。spin lock与semaphore的主要区别是spin lock是busy waiting,而semaphore是sleep。对于可以sleep的进程来说,busy waiting当然没有意义,CPU只是在那里空转而已,而且IRQL比较高,适合于等待时间比较短的场景。对于单CPU的系统,busy waiting当然更没意义(没有CPU可以释放锁),所有Spin lock只对多CPU才有意义,因此,只有多CPU的内核态非进程空间,才会用到spin lock。其实也就是类似mutex的作用,串行化对 critical section的访问。但是mutex不能保护中断的打断,也不能在中断处理程序中被调用。而spin lock也一般没有必要用于可以sleep的进程空间。幸好它是内核级的,如果是用户级的会很危险。      AutoResetEvent,ManualResetEvent (Event)

  这两种的实现都是基于WIN32的Event原理,同步事件有两种:AutoResetEvent 和 ManualResetEvent。它们之间唯一的不同在于,无论何时,只要 AutoResetEvent 激活线程,它的状态将自动从终止变为非终止。相反,ManualResetEvent 允许它的终止状态激活任意多个线程,只有当它的 Reset 方法被调用时才还原到非终止状态。

  ReaderWriterLockSlim

  这个也是lock的封装,对资源的访问方式有共享和独占方式,例如我们控制对某个资源读贡献或者写独占,那么这个类可以派上用场。

  SynchronizationAttribute ,MethodImplAttribute

  这两个属于类特性和方法的特性,标识某个类或方法是同步方法,本质上基于lock的实现。

  WaitHandle

  可以通过调用一种等待方法,如 WaitOne、WaitAny 或 WaitAll,让线程等待事件。  System.Threading.WaitHandle.WaitOne 使线程一直等待,直到单个事件变为终止状态;System.Threading.WaitHandle.WaitAny 阻止线程,直到一个或多个指示的事件变为终止状态;System.Threading.WaitHandle.WaitAll 阻止线程,直到所有指示的事件都变为终止状态。当调用事件的 Set 方法时,事件将变为终止状态。WaitOne基于WaitSingleObject,WaitAny 或 WaitAll基于WaitmultipleObject,具体由后面参数来决定。WaitmultipleObject实现要比WaitSingleObject复杂的多,性能也不好,尽量少用。

目录
相关文章
|
25天前
|
监控 测试技术 程序员
解决线程死循环问题的有效方法
作为开发者想必都清楚,多线程应用程序的开发为我们日常开发工作中提供了并发执行任务的能力,但线程死循环问题却是一个常见而令人头疼的挑战,因为线程死循环可能导致系统的不稳定性、资源浪费以及应用程序的异常运行,所以准确地定位和妥善处理线程死循环现象,并在编码阶段就避免潜在风险,成为开发人员必须面对的重要问题,线程死循环问题的解决不仅有助于提高系统的稳定性和可用性,还能优化资源利用和提升应用程序的性能,通过采取适当的预防和处理措施,开发人员能够避免线程陷入无尽的循环,并及时发现和解决潜在问题。那么本文就来分享一下关于如何处理线程死循环问题,以及如何在编码阶段规避潜在风险。
32 2
解决线程死循环问题的有效方法
|
27天前
|
API 网络安全 数据安全/隐私保护
.NET邮箱API发送邮件的方法有哪些
本文介绍了.NET开发中使用邮箱API发送邮件的方法,包括SmtpClient类发送邮件、MailMessage类创建邮件消息、设置SmtpClient属性、同步/异步发送、错误处理、发送HTML格式邮件、带附件邮件以及多人邮件。AokSend提供高触达发信服务,适用于大规模验证码发送场景。了解这些技巧有助于开发者实现高效、可靠的邮件功能。
|
4天前
|
存储 缓存 前端开发
Java串口通信技术探究3:RXTX库线程 优化系统性能的SerialPortEventListener类
Java串口通信技术探究3:RXTX库线程 优化系统性能的SerialPortEventListener类
20 3
|
6天前
|
Dart 前端开发 安全
【Flutter前端技术开发专栏】Flutter中的线程与并发编程实践
【4月更文挑战第30天】本文探讨了Flutter中线程管理和并发编程的关键性,强调其对应用性能和用户体验的影响。Dart语言提供了`async`、`await`、`Stream`和`Future`等原生异步支持。Flutter采用事件驱动的单线程模型,通过`Isolate`实现线程隔离。实践中,可利用`async/await`、`StreamBuilder`和`Isolate`处理异步任务,同时注意线程安全和性能调优。参考文献包括Dart异步编程、Flutter线程模型和DevTools文档。
【Flutter前端技术开发专栏】Flutter中的线程与并发编程实践
|
7天前
|
消息中间件 缓存 Java
【多线程学习】深入探究定时器的重点和应用场景
【多线程学习】深入探究定时器的重点和应用场景
|
12天前
|
缓存 Java 编译器
第一章 Java线程池技术应用
第一章 Java线程池技术应用
14 0
|
12天前
|
并行计算 算法 安全
Java从入门到精通:2.1.3深入学习Java核心技术——掌握Java多线程编程
Java从入门到精通:2.1.3深入学习Java核心技术——掌握Java多线程编程
|
13天前
|
并行计算 算法 Java
Java中的多线程技术实现与应用
【4月更文挑战第23天】本文将深入探讨Java中的多线程技术,包括其基本概念、实现方法以及在实际应用中的优势。我们将通过实例代码和应用场景,详细解析多线程技术在Java中的应用,以期帮助读者更好地理解和掌握这一技术。
|
14天前
|
Java
Java中的多线程技术实现
【4月更文挑战第22天】本文将深入探讨Java中的多线程技术实现,包括线程的创建、启动、同步和通信等方面。通过实例分析,我们将了解如何利用多线程提高程序的性能和效率。
8 2
|
15天前
|
NoSQL
线程死循环的定位方法
线程死循环的定位方法
17 2