Thread.Sleep(0)和Thread.Yield()之间的区别

26
Java早已有了Sleep和Yield,我在这里找到了针对Java的答案,但没有针对.NET的答案。
.NET 4 包含了新的Thread.Yield()静态方法。以前,将CPU交给其他进程的常见方式是Thread.Sleep(0)。

除了Thread.Yield()返回一个布尔值外,还有其他性能和操作系统内部的区别吗?

例如,我不确定Thread.Sleep(0)是否会在将当前线程切换为等待状态之前检查其他线程是否准备好运行......如果没有其他线程准备好运行,Thread.Sleep(0)似乎比Thread.Yield()更糟糕。
3个回答

12

如Eric Lippert在他的Coverity博客文章“C#中的锁是如何工作的?”中所解释的那样,在演示如何实现锁定时——

.NET Framework提供了多种工具,可以用来构建更复杂的等待策略:Thread.SpinWait将处理器置于紧密循环中,允许您等待几个纳秒或微秒而不将控制权移交给另一个线程。Thread.Sleep(0)将控制权移交给任何优先级相同的就绪线程或继续在当前线程上执行(如果没有就绪线程)。Thread.Yield将控制权移交给与当前处理器关联的任何就绪线程。正如我们所看到的,Thread.Sleep(1)将控制权移交给操作系统选择的任何就绪线程。通过仔细选择这些调用的组合并在真实条件下进行性能测试,您可以构建高性能的实现,当然这正是CLR团队实际所做的。


在这个上下文中,“处理器”到底是什么意思?是逻辑核心吗?还是物理芯片?在多核单处理器系统上,Sleep(0)Yield之间有区别吗? - AnT stands with Russia
链接已失效,但仍可通过互联网档案馆访问。建议编辑此链接以将其更新为https://web.archive.org/web/20161208024416/http://blog.coverity.com/2014/02/12/how-does-locking-work/。 - Toadfish

5
根据MSDN的说法, 使用Sleep(0)时, 线程将不会被操作系统安排在指定的时间内执行。
使用Yield()时, 线程的当前时间片的剩余部分将被让出。根据线程的优先级和其他可运行线程的状态,操作系统会安排调用线程的另一个时间片。
因此,两者之间有一些细微的差别。Thread.sleep会将线程置于SLEEP模式,并建议它在给定的毫秒数内保持在该模式下。 Thread.yield会将其置于WAIT模式,以便可以立即再次运行,或者更高优先级的进程线程可能会介入。

3
我认为在CLR或操作系统级别上没有“睡眠”状态,只有“等待”和“就绪”状态。我认为Yield可以直接转移到“就绪”状态,而Sleep(n>0)会转移到“等待”状态,一旦时间间隔结束,就会将其移动到“就绪”状态。 我认为Sleep(0)可以直接转移到“等待”状态,无需经过“睡眠”状态。 - Xose Lluis
2
@XoseLluis,尽管 Yield() 在功能上等价于 Sleep(0),但我更喜欢使用 Yield(),因为它清晰地表明了程序员的意图。 - Gerardo Lima
@GerardoLima -- 如果你关心 CPU 使用率,那么它们在功能上并不等价。Yield() 似乎比 Sleep(0) 使用更多的 CPU 百分比。 - rory.ap

4

Thread.Sleep(0) 立即放弃线程的当前时间片,自愿将CPU交给其他线程。

Framework 4.0 的新方法 Thread.Yield() 做同样的事情——除了它只放弃给运行在相同的处理器的线程。

来源


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接