首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >SpinWait vs睡眠等待。使用哪一个?

SpinWait vs睡眠等待。使用哪一个?
EN

Stack Overflow用户
提问于 2012-03-15 19:44:42
回答 2查看 71K关注 0票数 77

是否有效率?

代码语言:javascript
复制
SpinWait.SpinUntil(() => myPredicate(), 10000)

对于10000ms的超时

对于相同的条件,使用Thread.Sleep轮询是否更有效?例如,类似于下面的SleepWait函数:

代码语言:javascript
复制
public bool SleepWait(int timeOut)
{
    Stopwatch stopwatch = new Stopwatch(); 
    stopwatch.Start();
    while (!myPredicate() && stopwatch.ElapsedMilliseconds < timeOut)
    {
       Thread.Sleep(50)
    }  
    return myPredicate()
}

我担心,如果我们谈论的是超过1秒的超时,那么SpinWait的所有让步可能不是一个好的使用模式?这是一个有效的假设吗?

你更喜欢哪种方法?为什么?还有其他更好的方法吗?

更新-变得更加具体:

有没有办法让BlockingCollection脉冲在达到有限容量时成为休眠线程?我宁愿避免像Marc Gravel建议的那样一起忙碌地等待。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2012-03-15 19:49:40

最好的方法是有一些机制来主动检测(而不是被动地轮询它已经成为真的);这可以是任何类型的等待句柄,或者可能是带有WaitTask,或者可能是你可以订阅的你自己的event。当然,如果你做了那种“等待,直到发生了什么事情”,也就是说,仍然不如简单地将下一步工作作为回调来完成,这意味着:你不需要使用线程来等待。Task为此提供了ContinueWith,或者当event被触发时,您可以直接在它中执行这项工作。根据上下文,event可能是最简单的方法。然而,Task已经提供了您在这里讨论的大部分内容,包括“带有超时的等待”和“回调”机制。

是的,旋转10秒并不是很好。如果你想使用像你现在的代码一样的东西,如果你有理由期待一个短的延迟,但需要考虑一个更长的延迟--比如20ms的SpinWait,剩下的使用Sleep

Re注释;下面是我如何挂接一个“是否已满”机制:

代码语言:javascript
复制
private readonly object syncLock = new object();
public bool WaitUntilFull(int timeout) {
    if(CollectionIsFull) return true; // I'm assuming we can call this safely
    lock(syncLock) {
        if(CollectionIsFull) return true;
        return Monitor.Wait(syncLock, timeout);
    }
}

使用,在"put back into the collection“代码中:

代码语言:javascript
复制
if(CollectionIsFull) {
    lock(syncLock) {
        if(CollectionIsFull) { // double-check with the lock
            Monitor.PulseAll(syncLock);
        }
    }
}
票数 52
EN

Stack Overflow用户

发布于 2012-03-15 20:08:09

在.NET 4中,SpinWait会执行10次CPU密集型旋转,然后才会让步。但是,它不会在每个周期之后立即返回给调用者;相反,它会调用Thread.SpinWait通过CLR (本质上是操作系统)旋转一段设定的时间段。这段时间最初是几十纳秒,但随着每次迭代而加倍,直到10次迭代完成。这可以在旋转(CPU密集型)阶段的总时间内实现清晰度/可预测性,系统可以根据条件(核心数量等)进行调整。如果SpinWait处于自旋产生阶段的时间太长,它将周期性地休眠,以允许其他线程继续(有关更多信息,请参阅J. Albahari's blog )。这个过程保证了核心的忙碌...

因此,SpinWait将CPU密集型旋转限制在一定的迭代次数内,之后它会在每次旋转上生成时间片(通过实际调用Thread.YieldThread.Sleep),从而降低其资源消耗。它还将检测用户是否正在运行单核心计算机,如果是,则在每个周期上让步。

使用Thread.Sleep时,线程会被阻塞。但就CPU而言,这个过程不会像上面那样昂贵。

票数 134
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/9719003

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档