【发布时间】:2013-07-03 10:40:32
【问题描述】:
我对自旋锁的功能感到困惑。
自旋锁用于阻止进程重新调度。 但是,在只有一个核心的机器上,使用自旋锁有用吗? 防止上下文切换?
【问题讨论】:
我对自旋锁的功能感到困惑。
自旋锁用于阻止进程重新调度。 但是,在只有一个核心的机器上,使用自旋锁有用吗? 防止上下文切换?
【问题讨论】:
您的观察很好:在单处理器系统上,旋转等待资源是没有意义的,因为您最好尽早切换线程。互斥锁和信号量正是这样做的。
在多处理器系统上,另一个处理器上的线程可能会在没有上下文切换的情况下释放锁。然后,如果您不希望等待很长时间,自旋锁可能很有用,因为在其他线程解锁之前一直闲逛可能会更快。如果您在互斥锁上睡觉,则基本上可以确保在重新安排之前有一段相当长的空闲时间。
然而,在内核代码中,情况发生了变化:中断处理程序需要与内核的其余部分访问共享资源,但它们不能休眠。互斥锁会让内核进入睡眠状态,所以你不能使用它们,但是自旋锁也没有用,因为没有任何东西会中断单处理器上的中断处理程序(好吧,也许是另一个中断,但这很可怕)。
然后,在内核中,自旋锁在中断处理程序编译为无操作。正如您可能想象的那样,它们完全被忽略了。同时,为了防止竞争,自旋锁内核的其余部分在中断真正旋转之前禁用中断(因为可以调度内核任务)。这些代码只有在与中断处理程序共享代码时才需要自旋锁(与互斥锁相反)。
一般来说,你是对的:如果你有互斥锁,自旋锁在单处理器上真的没有多大意义,因为互斥锁浪费的时间更少。
【讨论】:
简短回答:不。
根据http://uw714doc.sco.com/en/man/html.3synch/Intro.3synch.html
不得在单处理器系统上使用自旋锁。在最好的情况下,单处理器系统上的自旋锁会浪费资源,减慢锁的所有者;在最坏的情况下,它会死锁处理器。
在单处理器系统上,不需要自旋锁,因为只有高 IRQL 才需要自旋锁同步。在高 IRQL(高于调度 IRQL)上,不会发生上下文切换,因此无需旋转获取线程,只需在相关 IRQL 上请求中断并返回即可;中断将被屏蔽,直到释放线程将 IRQL 降低到请求的 IRQL 以下。
对于单处理器系统,内核将忽略自旋计数值,并将其视为零 - 实质上使自旋锁成为空操作。
是的,自旋锁很有用,可以提高一些操作的效率。但是,通常您应该从互斥锁开始,如果分析表明它是一个瓶颈,您可能需要考虑使用自旋锁。
【讨论】:
是与否;取决于存在什么操作系统,如果有的话,以及你想要实现的目标。
如果您拥有完整的多任务和多线程操作系统,那么您必须从它为您提供的集合中选择您的原语,否则您将面临效率低下和最坏的同步无法工作的风险。每个操作系统都有自己的习惯用法和首选机制,不遵循这些约定也会付出代价。
您对完整内核的了解越深(或者您获得的内核和设备驱动程序越深入),您就会发现最好的习惯用法涉及较低级别的同步原语。
即使是单核 CPU 也具有可以(原则上)在任何指令对之间执行的中断处理程序,甚至在某些架构中的某些多周期指令期间也可以执行。这实际上是一种并发性,尽管比第二个内核弱,因此在前台线程和后台的任何中断处理程序之间进行通信时需要同步原语。当然,在单核中,前台线程之间的同步必须涉及上下文切换。
等待中断处理程序中设置的条件或硬件寄存器中设置的条件都是单核中的单个前台线程可能没有比旋转标志或寄存器更好的选择的情况。
编辑:我试图澄清这个答案,以明确我在谈论一般的同步,而不是任何特定操作系统的自旋锁实现。这个问题并不具体是什么操作系统(如果有的话),也没有针对任何特定的操作系统进行标记。
【讨论】:
没有。
有关更详细的答案,请参阅“How Do Locks Lock?”以及 cmets。
【讨论】: