什么是"自旋锁"?

RCI*_*CIX 94 spinlock

我总是想知道它们是什么:每当我听到它们的时候,未来派飞轮式设备的图像就会在我脑海里跳舞(滚动?)......

这些是什么?

Sed*_*glu 111

当您使用常规锁(互斥锁,关键部分等)时,操作系统会将您的线程置于WAIT状态,并通过调度同一核心上的其他线程来抢占它.如果等待时间非常短,则性能会受到影响,因为您的线程现在必须等待抢占才能再次接收CPU时间.

此外,内核对象在内核的每个状态中都不可用,例如在中断处理程序中或者在分页不可用时等.

自旋锁不会导致抢占,而是在循环中等待("旋转"),直到另一个核心释放锁定.这可以防止线程丢失其量程并在锁释放后立即继续.自旋锁的简单机制允许内核在几乎任何状态下使用它.

这就是为什么在单核心机器上,自旋锁只是一个"禁用中断"或"引发IRQL",这完全阻止了线程调度.

自旋锁最终允许内核避免"大内核锁定"(当核心进入内核并在出口处释放时获得锁定)并且对内核基元进行粒度锁定,从而在多核机器上实现更好的多处理,从而提高性能.

编辑:提出了一个问题:"这是否意味着我应该尽可能使用自旋锁?" 我会尽力回答:

正如我所提到的,Spinlocks仅在预期等待时间短于量子(读取:毫秒)的地方有用,并且抢占没有多大意义(例如,内核对象不可用).

如果等待时间未知,或者您处于用户模式,则Spinlocks效率不高.在检查自旋锁是否可用时,您在等待核心上消耗100%的CPU时间.在量程到期之前,您可以阻止其他线程在该核心上运行.此方案仅适用于内核级别的短突发,并且不太可能是用户模式应用程序的选项.

这是一个在SO处理的问题:Spinlocks,它们有用吗?

  • (然后禁用中断只是为了确保没有其他任务抢占您并弄乱资源)。在 UP(单处理器)上,情况总是如此:第一个(以及后续的)自旋锁被简单地授予,中断(即抢占)被禁用,并且使用资源的任务永远不会被抢占:它会执行其所有操作处理该资源,然后启用中断(从而抢占)。当启用抢占时,资源已经空闲。基本上,在 UP 上,*没有自旋锁争用*并且*没有等待*。在 SMP 上可能是这样。 (3认同)
  • 如果我错了,请纠正我,但自旋锁不会禁用抢占(即重新调度)。原因很简单,如果自旋锁正在等待另一个进程锁定的资源,那么必须给第二个进程一个运行并释放资源的机会。或者,运行第二个进程需要抢占第一个(旋转)进程。 (2认同)
  • 你是对的(另见:http://www.linuxjournal.com/article/5833),但事实是锁定资源和禁用中断虽然联合执行很有用,但在其他方面是不相关的概念。您基本上希望确保您没有使用处于不一致状态的资源,这就是您测试其锁的原因。禁用中断(也包括抢占)可以确保在您处理资源时没有人会弄乱您的资源。但是,为此,您必须确保在获取资源时该资源是免费的。 (2认同)

cod*_*ict 23

假设资源受锁保护,想要访问资源的线程需要首先获取锁.如果锁不可用,则线程可能会反复检查是否已释放锁.在此期间线程忙等待,检查锁,使用CPU,但没有做任何有用的工作.这种锁被称为旋转锁.

  • 很好的答案!+1 (2认同)

Ode*_*ded 17

这是一个循环,一直持续到满足某个条件:

while(cantGoOn) {};
Run Code Online (Sandbox Code Playgroud)

  • @Jiminion 如果你放置一个 `sleep(0)`,它会抢占线程,首先破坏使用自旋锁的目的。如果您需要让步给其他线程,则应该使用常规锁。(我知道您的评论很旧,但想防止其他人将此视为建议)。 (2认同)

Luk*_*hne 7

 while(something != TRUE ){};
 // it happend
 move_on();
Run Code Online (Sandbox Code Playgroud)


jan*_*nce 5

这是一种忙着等待的锁

它被认为是一种反模式,除了非常低级别的驱动程序编程(在这种情况下,调用"正确"的等待函数会比仅仅忙于锁定几个周期的开销更大).

请参阅Linux内核中的Spinlocks示例.