什么是“自旋锁”?

我总是想知道他们是什么样的人:每当我听到他们的声音,未来的飞轮式装置的图像就会在我脑海中跳舞(滚动)。

他们是什么?

当你使用常规的锁(互斥锁,关键部分等)时,操作系统会将你的线程置于WAIT状态,并通过在同一个内核上安排其他线程来抢占它。 如果等待时间非常短,这会导致性能损失,因为线程现在必须等待抢占才能再次接收CPU时间。

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

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

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

自旋锁最终允许内核避免“大内核锁”(当内核进入内核并在出口处释放时获得的锁),并对内核原语进行细粒度locking,从而在多核机器上实现更好的多处理性能,从而获得更好的性能。

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

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

如果等待时间未知,或者处于用户模式,则Spinlocks效率不高。 您在等待的核心上消耗100%的CPU时间,同时检查是否有自旋锁可用。 您阻止其他线程在该核心上运行,直到您的量程到期。 这种情况只适用于内核级别的短arrays,而不可能是用户模式应用程序的选项。

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

一直到一定条件满足为止,循环都是一个循环:

while(cantGoOn) {}; 

假设一个资源受到一个锁的保护,一个想要访问该资源的线程需要先获得该锁。 如果锁不可用,线程可能会重复检查锁是否已被释放。 在此期间,线程正忙着等待,使用CPU检查锁,但没有做任何有用的工作。 这种锁被称为自旋锁。

  while(something != TRUE ){}; // it happend move_on(); 

这是一种忙于等待的锁

它被认为是一种反模式,除了非常低级别的驱动程序编程(可能发生的情况是,调用“正确的”等待函数的花费比简单的繁忙locking几个周期更多)。

参见例如Linux内核中的Spinlocks 。

当你认为进入一个繁忙的等待循环比较便宜时,你会想要使用一个自旋锁,并且在资源被locking时将资源池而不是阻塞。

如果锁的细粒度和数量很大(例如,链表中的每个节点的锁)以及锁保持时间总是非常短,则旋转可能是有益的。 一般来说,在持有自旋锁的同时,应避免阻塞,调用任何本身可能阻塞的对象,同时持有多个自旋锁,dynamic调度(接口和虚拟),静态调用任何代码,拥有或分配内存。

出于性能的原因,SpinLock是一个值types也很重要。 因此,必须非常小心,不要意外地复制一个SpinLock实例,因为这两个实例(原始和副本)然后将是完全独立的,这可能会导致应用程序的错误行为。 如果必须传递一个SpinLock实例,它应该通过引用而不是按值传递。

SpinLock是线程等待locking可用的那个。 这通常用于避免在一段时间内获取内核对象的范围时获得内核对象的开销。

例如:

 While(SpinCount-- && Kernel Object is not free) {} try acquiring Kernel object 

简而言之,自旋锁使用primefaces比较和交换(CAS)或testing设置类似的指令来实现无锁,等待线程安全的成语。 这种结构在多核机器中很好地扩展。

这是一个循环,直到满足条件。

那么,是的 – 自旋锁(相对于传统的关键部分等)的关键在于它们在某些情况下(多核系统)提供更好的性能,因为它们不会立即产生线程的剩余部分。

旋转锁,是一种不可阻挡,不可睡眠的锁。 任何想要为任何共享资源或关键资源获取自旋锁的线程都将不断旋转,浪费CPU处理周期,直到获得指定资源的locking。 一旦获得了自旋锁,就试图完成它的量子工作,然后分别释放资源。 Spinlock是最高优先级的锁,简单的说就是,它是非抢先式的锁。