Answers:
一个区别是SemaphoreSlim
不允许使用命名信号量,该信号量可以在系统范围内使用。这意味着SemaphoreSlim不能用于跨进程同步。
MSDN文档还指出,当“等待时间预计非常短”时,应使用SemSlim。通常,在大多数折衷方案中,细长型版本的重量更轻,这通常可以很好地与之吻合。
SemaphoreSlim
是使用SpinWait实现的,因此,如果您等待很多,则会浪费大量CPU时间。如果您的进程是计算机上唯一的进程,那甚至不是一个好主意。
SemaphoreSlim基于SpinWait和Monitor,因此等待获取锁的线程正在燃烧CPU周期一段时间,以期在屈服于另一个线程之前获取锁。如果这没有发生,则一旦操作系统再次调度该线程,线程将允许系统切换上下文并再次尝试(通过消耗一些CPU周期)。经过长时间的等待,此模式可能会消耗大量的CPU周期。因此,实现这种情况的最佳方案是大多数时候没有等待时间,而您几乎可以立即获得该锁。
Semaphore依赖于OS内核中的实现,因此,每次获取锁时,您都会花费大量的CPU周期,但是此后,线程只是为了获得锁而睡眠了必要的时间。
关于“短时间”争议:
至少SemaphoreSlim MSDN文档指出:
SemaphoreSlim类是建议在单个应用程序内进行同步的信号量。
在备注部分。同一部分还说明了Semaphore和SemaphoreSlim之间的主要区别:
SemaphoreSlim是不使用Windows内核信号量的Semaphore类的轻量级替代。与Semaphore类不同,SemaphoreSlim类不支持命名系统信号。您只能将其用作本地信号灯。
[SemaphoreSlim and other locks] use busy spinning for brief periods before they put the thread into a true Wait state. When wait times are expected to be very short, spinning is far less computationally expensive than waiting, which involves an expensive kernel transition
我在这里查看了源代码,这是我想到的:
Semaphore和SemaphoreSlim都源自内部使用Win32本机句柄的WaitHandle。这就是为什么您都需要同时Dispose()的原因。因此,Slim是轻量级的概念值得怀疑。
SemaphoreSlim内部使用SpinWait,而Semaphore不使用。这告诉我,在预期等待时间较长的情况下,Semaphore至少应在不停止CPU的意义上做得更好。