C# Thread.Sleep(0)有什么用?
https://www.zhihu.com/question/404549155/answer/1321501865
C# Thread.Sleep(0)有什么用?
C# 异步编程_哔哩哔哩 (゜-゜)つロ 干杯~-bilibili
问题出现在视频的最后,sleep(0)和yield为什么可以发现多线程代码中的BUG,可以解释一下吗,谢谢
关注者
55
被浏览
17,374
登录一下,更多精彩内容等你发现
贡献精彩回答,参与评论互动
正在找工作⎝
回答这个要先从线程时间精度(时间片)开始说起。
很多参考书说,默认情况下,时间片为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 是有重大区别的。