您发现自己在代码中实际使用自旋锁的频率有多高?使用繁忙循环实际上优于使用锁的情况有多常见?
就我个人而言,当我编写某种需要线程安全的代码时,我倾向于使用不同的同步原语对其进行基准测试,就目前而言,使用锁似乎比使用自旋锁具有更好的性能。无论我实际持有锁的时间有多短,使用自旋锁时收到的争用量都远远大于使用锁时收到的争用量(当然,我在多处理器计算机上运行测试)。

我意识到在“低级”代码中更有可能遇到自旋锁,但我很想知道您是否发现它在更高级的编程中有用?

有帮助吗?

解决方案

这取决于你在做什么。在一般的应用程序代码,你要避免自旋锁。

在低层次的东西在那里你会只能容纳一两个指令的锁,延迟是很重要的,一个自旋锁垫比锁更好的解决方案。但这些情况是罕见的,尤其是在种其中C#,通常使用的应用程序。

其他提示

对于我的实时工作,特别是设备驱动程序,我用他们公平一点。事实证明,(当最后我计时本)等待像绑在硬件信号量同步对象中断嚼了至少20微秒,不管它实际上需要多长时间发生中断。存储器映射寄存器硬件的单个检查,随后进行检查,以RDTSC(以允许一个超时这样就不会锁住机)是在高nannosecond范围(basicly倒在噪声)。对于硬件级握手,不应该花太多时间的话,那真的是很难被击败,一个自旋锁。

我2c:如果您更新,满足一些访问标准,那么他们是很好的调节锁候选人:

  • 快速, ,即你将有时间取得调节锁,执行更新和发行的调节锁在一个单一的线量子,以便你不会先发制,同时保持调节锁
  • 本地化 所有数据的更新都是优选的一个单页面已经装载的,你不想要一个TLB当你保持调节锁,并且你依旧不想一页的错交换阅读!
  • 原子 你不需要任何其他锁定执行操作的,即。永远等待锁下的调节锁.

对于任何有任何潜在产量,应使用通知锁结构(事件、互斥、信号等等)。

一个用例自旋锁是,如果你期望非常低的争夺,但将会有很多他们的。如果您不需要为递归锁定的支持,一个自旋锁可以在单个字节来实现的,如果竞争是非常低的,则CPU周期浪费是可以忽略不计。

有关实际使用的情况下,我经常有成千上万个元素,其中更新所述阵列的不同元件可以并行的方式安全发生的阵列。两个线程试图在同一时间更新同一元素的几率是非常小的(低的竞争),但我需要为每一个元素(我将有很多他们)一个锁。在这些情况下,我通常分配我更新并行相同的尺寸的阵列的ubytes的阵列和内联实现自旋锁为(在d的编程语言):

while(!atomicCasUbyte(spinLocks[i], 0, 1)) {}
    myArray[i] = newVal;
atomicSetUbyte(spinLocks[i], 0);

在另一方面,如果我不得不用常规的锁,我将不得不指针数组分配给对象,然后分配一个互斥对象为这个阵列的每个元件。在方案如上面描述的,这只是简单的浪费。

如果你有性能关键代码您已经确定它需要速度比它目前是您已确定的关键因素是锁速度,那么它会是一个好主意,尝试自旋锁。在其他情况下,何必呢?正常锁更容易正确使用。

请注意以下几点:

  1. 最mutexe的实现旋转了一小时之前线实际上是不定期的.因此很难比较这些互斥与纯粹的自旋锁.

  2. 几个线程纺"尽快"的同样的调节锁将consome所有的带宽和drasticly减少程序的效率。你需要增加微小的"沉睡的"时间通过增加noop在你的纺循环。

您几乎不需要使用应用程序代码中的自旋锁,如果有的话,你应该避免使用它们。

我不能的任何理由使用在一个普通的操作系统上运行的C#代码自旋锁的事情。忙锁大多是在应用层面的浪费 - 纺纱可以使你使用整个CPU时间片,VS,如果需要锁定的状态会立即引起上下文切换。

,你必须NR线程处理器/内核可能在某些情况下,受益的= NR,但如果需要性能优化在该级别您可能使下一代3D游戏,与较差的同步原语的嵌入式OS工作高性能代码,创建一个OS /驱动程序或在任何情况下不使用C#。

我在我的程序中使用了自旋锁来实现垃圾收集器的停止世界阶段 HLVM 项目,因为它们很简单,而且是一个玩具虚拟机。然而,在这种情况下,自旋锁可能会适得其反:

Glasgow Haskell 编译器的垃圾收集器中的一个性能错误非常烦人,以至于它有一个名字,“最后核心减速”。这是他们在 GC 中不当使用自旋锁的直接后果,并且由于其调度程序而在 Linux 上加剧,但事实上,只要其他程序竞争 CPU 时间,就可以观察到这种影响。

第二张图的效果很明显 这里 可以看出影响的不仅仅是最后一个核心 这里, ,其中 Haskell 程序的性能下降超过 5 个核心。

始终保持这些观点在你的心中,而使用 自旋锁:

  • 快用户的方式执行。
  • 同步线在一个单一的过程中,或多个进程如果在共享内存。
  • 不返回,直到对象是拥有。
  • 不支持递归。
  • 消耗100%的CPU的话,"等待"。

我亲眼见过这么多的僵局只是因为有人认为这将是一个很好的想法,到使用自旋锁.

是非常非常小心,同时使用自旋锁

(我不能强调这足够了)。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top