【发布时间】:2009-07-07 08:56:48
【问题描述】:
来自MSDN 并不是很清楚它的用途。
可以用来模拟密集的CPU计算测试吗?
【问题讨论】:
标签: .net multithreading
来自MSDN 并不是很清楚它的用途。
可以用来模拟密集的CPU计算测试吗?
【问题讨论】:
标签: .net multithreading
没有。它用作非常短期的睡眠电话的替代品。
当您执行多线程锁定时,如果您尝试获取的资源已被锁定,您通常会进入睡眠状态并等待它变得空闲。当你这样做时,你放弃了调度程序分配给你的剩余时间来使用处理器,以便其他人可以尝试。 通常这很好,特别是对于长时间的等待,比如等待 IO,在等待磁盘主轴旋转时,其他进程的负载可以在 CPU 上运行。
但是,有时,您需要等待很短的时间。在这些情况下,您通常会放弃剩余的时间,并等待所有其他线程完成他们的工作,然后再进行另一次尝试。所以您可以作弊,而不是等待,您坐在那里不断轮询“我们快到了吗?有吗?方式。如果锁只保留了你剩余时间的一小部分,这将成为一种非常有效的等待方式,它也非常有效,因为调度程序不必参与重新安排所有其他线程来使用你放弃的时间如果你正常等待。
显然,如果您每次想要锁定时都旋转,那么您将不会很受欢迎,您的应用程序会变得迟缓并使用 100% 的 CPU,但是在非常小的剂量下,在正确的时间,它会使应用响应更快。
如果您现在正在考虑“我应该什么时候使用它?”,这是一个棘手的调用 - 如果您的资源经常被锁定和解锁非常快,那么围绕它的自旋锁而不是等待是一个好主意(然后测试您的应用程序的性能),如果您尝试短时间旋转,然后回到正常等待,这也是一种合理的方式。但一般来说,您永远不需要使用它。
【讨论】:
SpinWait 很少会导致您卡在 100% 的 CPU 利用率上。这是因为如果它旋转太久,它开始导致线程屈服或休眠。具体来说,如果旋转次数大于或等于 10,则每 19 次旋转将sleep(1),每 4 次旋转将sleep(0),并且当且仅当确定下一次旋转具有屈服潜力时yield .它可以在任何时候在多处理器系统上sleep 或yield,并且不需要等待最初的 10 次旋转。在单处理器系统上,只有在旋转计数为 10 或以下时才会sleep 或yield。
Thread.SpinWait()(问题和答案)与var sw = new SpinWait(); sw.SpinOnce(); 混淆了,后者将内部旋转计数到10 ...
如果您相信您等待的条件会非常非常快实现,那么目的是进行“廉价”等待。通常,如果您正在等待某些东西,您会让线程进入睡眠状态,处理器/操作系统将上下文切换到另一个线程。上下文切换并不是特别便宜,所以如果您对情况有深入的了解,并且认为等待比上下文切换更便宜,那么您就可以等待。
我的建议:如果你需要问,你不需要使用它。 (我自己从来不想要它。)基本上它是在极少数情况下真正有用的东西之一,但大多数人应该别管它。
【讨论】:
附带说明,Microsoft 已经从 Windows 7 中删除了线程调度程序自旋锁机制,因为它不能很好地扩展到多核 CPU。看看this:
【讨论】:
就我而言(我很高兴进行更正!),自旋等待的唯一用途是在实现锁定或线程间回调机制时。并且两者都不应该手动完成(通常),因为它们已经存在。
当你锁定一个资源并且另一个线程请求同步访问它时,它基本上必须等待第一个线程完成使用它。这种等待可以通过简单地循环来完成(或者乔恩提到的睡眠+上下文切换)。
【讨论】:
Render() 周期内限制帧速率。其他Sleep() 机制都没有提供足够好的保证您何时会被切换回来。