我如何选择Semaphore和SemaphoreSlim?

Mic*_*eth 98 c# multithreading semaphore

他们的公共界面看似相似.该文档指出SemaphoreSlim是一种轻量级替代方案,不使用Windows内核信号量. 该资源表明SemaphoreSlim速度更快.SemaphoreSlim在什么情况下对信号量更有意义,反之亦然?

And*_*ber 60

一个区别是SemaphoreSlim不允许命名的信号量,它可以是系统范围的.这意味着SemaphoreSlim不能用于跨进程同步.

MSDN文档还指出,当"等待时间预计非常短"时,应该使用SemSlim.这通常与这样的想法相吻合,即超薄版本在大多数折衷方面更轻巧.

  • ......或"非常短"的意思 (66认同)
  • 我希望MS写下一些关于等待时间不是"非常短"时会发生什么的事情. (55认同)
  • 根据系统的不同,Semaphore为1微秒,SemaphoreSlim为1/4微秒进行WaitOne或Release ["C#5.0 in a Nutshell"pg.890]所以也许这就是他们在很短的等待时间里的意思? (8认同)
  • @culix查看Semaphore与SemaphoreSlim的来源我怀疑SemaphoreSlim仅用于"非常短"的等待的主要原因是因为它使用了旋转等待.这种响应速度更快,但是占用大量的CPU,并且对于瞬时响应不那么重要的较长等待时间会浪费.信号量阻塞了线程. (4认同)
  • @dhsto很好的参考!但我猜测链接文章意味着"当等待访问共享资源的时间非常短"时 - 即资源不会长时间保持独占使用 - 而不是意味着信号量代码本身的等待时间?无论资源保持锁定多长时间,信号量代码都将始终执行. (2认同)

Joe*_*Joe 16

MSDN文档描述了差异.

用一句话:

  • SemaphoreSlim类表示一个轻量级,快速的信号量,当等待时间预计非常短时,可用于在单个进程内等待.

  • @Salgat你为什么这样做?正如其他答案所述,`SemaphoreSlim`是使用SpinWait实现的,所以如果你等了很多,你将浪费大量的CPU时间.如果您的流程是计算机上唯一的流程,那么这也不是一个好主意. (2认同)

小智 12

SemaphoreSlim基于SpinWait和Monitor,因此等待获取锁的线程正在燃烧CPU周期一段时间,希望在屈服于另一个线程之前获取锁.如果没有发生这种情况,那么一旦操作系统再次调度该线程,线程就会让系统切换上下文并再次尝试(通过刻录一些CPU周期).等待很长时间,这种模式可能会耗费大量的CPU周期.因此,这种实现的最佳情况是大部分时间没有等待时间,您几乎可以立即获得锁定.

Semaphore依赖于OS内核中的实现,因此每次获得锁时,都会花费相当多的CPU周期,但在此之后,线程只需休眠一段时间就可以获得锁定.


小智 8

关于"短时间"的争议:

至少SemaphoreSlim MSDN文档说明了这一点

SemaphoreSlim类是在单个应用程序中同步的推荐信号量.

在备注部分.同一部分还讲述了Semaphore和SemaphoreSlim之间的主要区别:

SemaphoreSlim是Semaphore类的轻量级替代品,它不使用Windows内核信号量.与Semaphore类不同,SemaphoreSlim类不支持命名系统信号量.您只能将其用作本地信号量.

  • 更多详细信息:“[SemaphoreSlim 和其他锁] 在将线程置于真正的等待状态之前,会使用短暂的忙旋转。当等待时间预计非常短时,旋转的计算成本远低于等待,这涉及昂贵的内核转换:https://dotnet.github.io/docs/essentials/collections/thread-safe-collections.html (3认同)