为什么自旋锁在 Linux 内核设计中是不错的选择,而不是在用户态代码中更常见的东西,例如信号量或互斥锁?

Sen*_*Sen 7 linux semaphore spinlock

我知道自旋锁在 Linux 内核设计中是真正的浪费。

我想知道为什么自旋锁在 Linux 内核设计中是不错的选择,而不是在用户态代码中更常见的东西,例如信号量或互斥锁?

小智 11

正如这个问题暗示自旋锁是一种“浪费”,自旋锁应该只被短暂持有。

自旋锁不是同步多个线程的唯一方法。Linux 内核中也使用了互斥体/信号量,以及其他同步原语(例如等待队列、事件)。

然而,内核必须处理用户空间从未见过的情况,一个常见的情况是中断处理程序。中断处理程序不能在 Linux 上重新调度,但通常必须使用一些同步原语(例如,将工作项添加到某个其他线程将进一步处理的链表中)。由于中断处理程序无法休眠,因此它们无法使用互斥锁、等待队列等。这几乎会留下自旋锁。如果线程需要与中断处理程序同步访问,那么它也必须使用相同的自旋锁。

自旋锁不一定是浪费。它们针对非争用/非等待情况进行了优化,可以非常快速地获取和发布。在这种情况下,它们比其他同步原语更快并且涉及更少的开销。


Ric*_*chm 8

自旋锁和另一个导致调用者阻塞和放弃对 CPU 的控制的构造之间的选择在很大程度上取决于执行上下文切换(在锁定线程中保存寄存器/状态和恢复寄存器/状态)所花费的时间在另一个线程中)。这样做所花费的时间和缓存成本可能会很大。

如果使用自旋锁来保护对硬件寄存器或类似的访问,其中任何其他正在访问的线程在释放锁之前只需要几毫秒或更短的时间,那么最好利用 CPU 时间进行自旋等待而不是上下文切换并继续。