这段代码几乎不消耗CPU(i5系列)
public void SpinWait() {
for (int i = 0; i < 10000; i++)
{
Task.Factory.StartNew(() =>
{
var sw = new SpinWait();
while (true)
{
sw.SpinOnce();
}
});
}
}
在我的代码中,与SemaphoreSlim相比,当旋转真正被证明是必要的情况下(5 Mops),性能差异达到3倍或更多。然而,我担心长时间等待时使用它。标准建议是实现两阶段等待操作。我可以检查 NextSpinWillYield
属性,并引入计数器+重置以增加默认旋转迭代次数而不产生收益,然后再回到信号量。
但是,仅使用 SpinOnce
进行长期等待有什么缺点?我已经查看了其 implementation,并且在需要时它会正确地产生收益。它使用 Thread.SpinWait
,在现代CPU上使用PAUSE指令,并根据Intel非常高效。
ThreadPool.SetMaxThreads
来解决,然后线程数就固定了,CPU 使用率仍然接近零。如果长时间等待的任务数量有限,那么使用
SpinWait.SpinOnce
进行长期等待会有哪些其他陷阱?它是否取决于 CPU 家族、操作系统、.NET 版本?(只是为了澄清:我仍然会实现两阶段等待,我只是好奇为什么不一直使用 SpinOnce?)
semaphore.WaitAsync(-1, token)
上等待,线程唤醒需要多少微秒?如果我使用自旋等待并且SpinOne
在Sleep(1)
后让出,那么在最坏的情况下,如果信号恰好在调用Sleep(1)
后到达,我会引入至少 15 毫秒的延迟。如果我改用信号量,那么线程在semaphore.Release()
后唤醒的最坏延迟是多少? - V.B.