C# Thread.Sleep(0)有什么用?

C# Thread.Sleep(0)有什么用?

https://www.zhihu.com/question/404549155/answer/1321501865

C# Thread.Sleep(0)有什么用?

 

C# 异步编程_哔哩哔哩 (゜-゜)つロ 干杯~-bilibili​

www.bilibili.com图标

问题出现在视频的最后,sleep(0)和yield为什么可以发现多线程代码中的BUG,可以解释一下吗,谢谢

关注者

55

被浏览

17,374

登录一下,更多精彩内容等你发现

贡献精彩回答,参与评论互动

查看全部 15 个回答

羊牮

羊牮

正在找工作⎝

回答这个要先从线程时间精度(时间片)开始说起。

很多参考书说,默认情况下,时间片为15ms 左右,但是这是已经过时的知识。

在老的 Windows 操作系统里,应用程序模式时时间片 15ms 左右,准确一点是15.625 左右。服务器模式是其双倍。

但是在微软推行.Net 普及 Task之后,规则已经改动,并且做了精细的调节。

现在Win10的时间精度为1ms(不用担心谷歌浏览器修改时间精度了),Win2013服务器的时间精度为7ms,使用微软提供的测试工具可以测出来。

谢谢下面评论提供的命令行:powercfg /energy

我们可以通过它可以更直观的看出:

因为有这个请求在,所以无论如何最低的计时器分辨率都只能为1ms。

所以,现在Win10 默认状态下,Sleep(1) 占时不再是15ms,而是1ms 左右:

14167 即 1.4167ms


 

下面现在正式回答,Thread.Sleep(0)Thread.Yield()Thread.Sleep(1) 有什么不同:

首先,Thread.Sleep 只是放弃时间片的剩余时间,让系统重新选择调度一个合适的线程(其优先级等于或者高于当前线程)。在没有其他活动线程的情况下,使用Sleep(0) 还是选上原来线程,即连任,如果连任了,系统不会对其做上下文切换,所以有:

其次,Thread.Yield() 是什么呢?跟 Thread.Sleep 有点像,但是它跟 Thread.Sleep(0) 有点区别:系统选择继任时可以选择优先级比原来低的线程。

最后,Thread.Sleep(1) 是什么情况呢?前面说了,Thread.Sleep 只是放弃时间片的剩余时间,让系统重新选择调度一个合适的线程。但是 Thread.Sleep(1) 却让当前线程沉睡了(即使只有1ms )。也就是说,主动放弃下次竞选,所以不可能连任,系统上下文必然发生切换(优先级低于原线程的家伙也有机会)。

以上。

 

有的答主的答案是错的:


错误答案1:

Sleep(0) 不能降低CPU的占有率,只是改变了跟其他线程的占有比例,Sleep(0) 在没有其他活动线程的情况下会马上返回。

 


错误答案2:

这个知识点不知道从何而来,难道是更老的 Windows?


错误答案3:

如前所述,Sleep(0) 和 Yield 是有重大区别的。

编辑于 07-06