在用于 Semaphore 的 WaitOne(Int32) 方法的 MSDN docs 中,它说给它一个零值将导致该方法立即返回,而无需等待插槽打开。 SemaphoreSlim 版本的文档没有说明同样的事情。 SemaphoreSlim 是否也有这种行为?
我不确定如何保证自己测试的时间。
最佳答案
如果超时为 0,那么 SemaphoreSlim.Wait
将始终尝试在返回之前获取一个插槽,它只是不会等待一个比几个操作和一个 SpinOnce
更长的时间。
编辑:澄清: 这可能与 Semaphore
的明显行为相同。来自 Semaphore
的文档:
但是 SemaphoreSlim
确实通过使用 SpinOnce
为您在 Wait 方法中提供了打开插槽的机会。
(结束编辑)
此外,SemaphoreSlim
在尝试获取插槽之前运行一些操作。其中之一是 Monitor.Enter
,因此它可以在此时等待正在等待或释放过程中的其他线程。因此,它不一定会立即返回。
据我所知,事件的顺序是:
CancellationTokenRegistration
SpinWait.SpinOnce
(如果 NextSpinWillYield
是 true
则跳过此)(编辑:我大胆强调第 2 步执行与第 5 步相同的测试,让它有机会旋转并在最终测试和退出之前有一个可用的插槽)
Monitor.Enter
进入锁(Release 和 WaitAsync 进入的同一个锁) false
AvailableWaitHandle
下的 waitHandle,如果它正在被使用并且可用插槽计数现在再次为 0 CancellationTokenRegistration
true
(请注意,其他使用非零超时的线程会通过调用
Monitor.Wait
间歇性地释放和获取用于保护计数器的锁,因此您不会在超时为 0 的情况下永远等待,只是很短的时间。)因此
SemaphoreSlim
似乎不会与 Sempahore
共享完全相同的 0 超时行为,因为它确实为插槽提供了打开的机会。 (也许这就是为什么有 Semaphore.WaitOne
和 SemaphoreSlim.Wait
- 通过更改信号量的实例化来升级旧代码时导致代码无法编译,从而让我们检查行为)。文章 Semaphore vs. SemaphoreSlim 没有强调这种行为,只是强调两者之间的根本区别。
边注:
有趣的是,该引用文献还指出
然而 SemaphoreSlim.AvailableWaitHandle 的文档却有不同的说法。
关于c# - SemaphoreSlim 的 Wait(Int32) 方法在传递为零时是否立即返回?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/14574181/