其他分享
首页 > 其他分享> > 一文看懂 Mutex vs Semaphore vs Monitor vs SemaphoreSlim

一文看懂 Mutex vs Semaphore vs Monitor vs SemaphoreSlim

作者:互联网

C#开发者(面试者)都会遇到Mutex,Semaphore,Monitor,SemaphoreSlim这四个与锁相关的C#类型,本文期望以最简洁明了的方式阐述四种对象的区别。

什么叫线程安全?

教条式理解

如果代码在多线程环境中运行的结果与 单线程运行结果一样,其他变量值也和预期是一样的,那么线程就是安全的;

线程不安全就是不提供数据访问保护,可能出现多个线程先后修改数据造成的结果是脏数据。

实际场景理解 

两个线程都为集合增加元素,我们错误的理解即使是多线程也总有先后顺序吧,集合的两个位置先后塞进去就完了;实际上集合增加元素这个行为看起来简单,实际并不一定是原子操作。

在添加一个元素的时候,它可能会有两步来完成:

  1. 在 Items[Size] 的位置存放此元素;
  2. 增大 Size 的值。

线程安全这个问题不单单存在于集合类,我们始终要记得:
Never ever modify a shared resource by multipie threads unless resource is thread-safe.

各语言推出了适用于不同范围的线程同步技术来预防以上脏数据(实现线程安全)。

C#线程同步技术

话不多说, 给出大图:

四象限对象的区别:

该线程同步技术

  -  支持线程进入的个数

       -  是否跨进程支持 

其中

 ① lock  vs Monitor

最常用的lock关键字,能在多线程环境下确保只有一个线程在执行 {被保护的代码},其他线程则必须等待进入的线程完成工作代码。

上图将lock和Monitor放在一起,是因为lock是Monitor的语法糖,实际的编译代码如下:

bool lockTaken = false;
try
{
  Monitor.Enter(obj, ref lockTaken);
  //...
}
finally
{
  if (lockTaken) Monitor.Exit(obj);
}

 ② lock(Monitor)vs Mutex(中文称为互斥锁,互斥元)

lock/Monitor 维护进程内线程的安全性,Mutex 维护跨进程的线程安全性。

这2个对象都只支持单线程进入指定代码。

 ③ SemaphoreSlim  vs Semaphore 

 中文都称为信号量,根据对象初始化的配置,能够允许单个或多个线程进入保护代码。

信号量使多个并发线程可以访问共享资源(最大为您指定的最大数量),当线程请求访问资源时,信号量计数递减,而当它们释放资源时,信号量计数又递增。

SemaphoreSlim 是一个轻量级的,由CRL支持的进程内信号量。

 右侧Mutex 和Semaphore 都是内核对象,可以看到他们都继承自WaitHandle对象,

 左侧Monitor,SemaphoreSlim是.NET CLR对象,

④ Monitor  vs SemaphoreSlim

  两者都是进程内线程同步技术,SemaphoreSlim信号量支持多线程进入;

 另外SemaphoreSlim 有异步等待方法,支持在异步代码中线程同步, 能解决我们在async code中无法使用lock语法糖的问题;

// 实例化单信号量
static SemaphoreSlim semaphoreSlim = new SemaphoreSlim(1,1);

//Asynchronously wait to enter the Semaphore. If no-one has been granted access to the Semaphore, code execution will proceed, otherwise this thread waits here until the semaphore is released 
await semaphoreSlim.WaitAsync();
try
{
    await Task.Delay(1000);
}
finally
{
    //When the task is ready, release the semaphore. It is vital to ALWAYS release the semaphore when we are ready, or else we will end up with a Semaphore that is forever locked.
    //This is why it is important to do the Release within a try...finally clause; program execution may crash or take a different path, this way you are guaranteed execution
    semaphoreSlim.Release();
}

总结:

象限图中快速知晓 这4种线程同步技术的区别:

-   是否支持跨进程线程同步

-   是否支持多线程进入被保护代码。

标签:SemaphoreSlim,Monitor,信号量,vs,Mutex,Semaphore,线程,Size
来源: https://www.cnblogs.com/JulianHuang/p/11765397.html