Thread.SpinWait方法的目的是什么?

Dra*_*ake 60 .net multithreading

来自MSDN的目的并不是很明确.

它可以用来模拟密集的CPU计算测试吗?

gbj*_*anb 106

没有.它用作非常短期睡眠呼叫的替代品.

当您执行多线程锁定时,如果您尝试获取的资源已被锁定,则通常会进入休眠状态并等待它变为空闲状态.执行此操作时,您将放弃由调度程序分配的其余时间以使用处理器,以便其他人可以进行操作.通常情况下这很好,特别是对于等待IO的长时间等待,当您等待磁盘轴旋转时,其他进程的负载可以在CPU上运行.

但是,有时候,你会等待很短的时间.在这些情况下,你通常会放弃你的剩余时间,并等待所有其他线程做他们的事情再去另一个..所以你可以作弊,而不是等待,你坐在那里不断轮询'我们差不多还有吗?办法.如果锁只保留了剩余时间的一小部分,这将成为一种非常有效的等待方式,它也非常有效,因为调度程序不必参与重新排列所有其他线程以使用你放弃的时间如果你正常等待

显然,如果你每次想要锁定时旋转,你就不会非常受欢迎,你的应用程序会变得迟钝并使用100%的CPU,但是在非常小的剂量下,在适当的时候,它会使应用程序更具响应性.

如果您现在正在考虑"我应该何时使用它?",这是一个棘手的调用 - 如果您拥有一个经常被锁定并且很快解锁的资源,那么围绕它而不是等待的自旋锁是一个好主意(然后测试你的应用程序的性能),如果你尝试旋转一小段时间,然后回到正常的等待,这也是一个合理的方式.但一般来说,你永远不需要使用它.

  • @ MichaelJ.Gray:你用`var sw = new SpinWait()混淆了`Thread.SpinWait()`(问题和答案); sw.SpinOnce();`执行内部旋转计数直到10 ... (4认同)
  • `SpinWait`很少会让你陷入100%的CPU利用率.这是因为如果它旋转太久,它会开始导致线程产生或睡眠.具体来说,如果旋转次数大于或等于10,则每第19次旋转都会"睡眠(1)",每次第4次旋转都会"睡眠(0)",当且仅当下次旋转时,"屈服"决心产生潜力.它可以在任何时候在多处理器系统上"睡眠"或"产生",并且不需要等待最初的10次旋转.在单处理器系统上,如果旋转计数为10或更低,它将只"睡眠"或"屈服". (3认同)
  • @CharlesOkwuagwu几十毫秒,你可能会用一个简单的thread.sleep更好. (2认同)

Jon*_*eet 77

如果您认为您所等待的条件将很快实现,那么目的就是做一个"便宜"的等待.通常,如果你正在等待什么,你让线程进入休眠状态,处理器/操作系统将上下文切换到另一个线程.上下文切换并不是特别便宜,所以如果你对这种情况有了深入的了解,并且相信等待上下文比上下文更便宜,你就可以等待.

我的建议是:如果你需要问,你不需要使用它.(我自己从来不想要它.)基本上它是在极少数情况下非常有用的东西之一,但大多数人应该独自留下.

  • 我想这个与"除非你已经测量并发现存在问题......"的整个类别一致. (3认同)

Jas*_*ans 15

作为旁注,微软已经摆脱了Windows 7中的线程调度器自旋锁机制,因为它不能很好地扩展到多核CPU.看看这个:

  • 它说他们已经摆脱了他们在Windows中使用的一个螺旋锁 - 调度员螺旋锁. (2认同)

Kon*_*lph 6

就我而言(我很高兴纠正!),旋转等待的唯一用途是实现锁定或线程间回调机制.并且都不应该手动(通常)完成,因为它们已经存在.

当您锁定资源而另一个线程请求对其进行同步访问时,它基本上必须等待第一个线程完成使用它.这种等待可以通过简单地在循环中旋转(或者如Jon所提到的睡眠+上下文切换)来完成.

  • 一个例外 - 在游戏引擎的'Render()`循环中,以限制帧速率.其他`Sleep()`机制都没有提供关于何时切换回来的足够好的保证. (2认同)
  • @Basic True虽然经常做的是你在渲染周期中跳过圈数而不是有一个显式(嵌套)等待循环.效果当然是一样的. (2认同)