【发布时间】:2010-12-29 18:25:38
【问题描述】:
我一直想知道它们是什么:每次我听到它们时,未来派飞轮类设备的图像都会在我脑海中翩翩起舞(滚动?)......
它们是什么?
【问题讨论】:
标签: spinlock
我一直想知道它们是什么:每次我听到它们时,未来派飞轮类设备的图像都会在我脑海中翩翩起舞(滚动?)......
它们是什么?
【问题讨论】:
标签: spinlock
当您使用常规锁(互斥锁、临界区等)时,操作系统会将您的线程置于 WAIT 状态并preempts 通过在同一核心上调度其他线程来将其置于。如果等待时间真的很短,这会降低性能,因为您的线程现在必须等待抢占才能再次接收 CPU 时间。
此外,内核对象并非在内核的每个状态下都可用,例如在中断处理程序中或分页不可用时等。
自旋锁不会导致抢占,而是在循环中等待(“自旋”),直到另一个核心释放锁。这可以防止线程丢失其quantum 并在锁被释放后立即继续。自旋锁的简单机制允许内核在几乎任何状态下使用它。
这就是为什么在单核机器上,自旋锁只是“禁用中断”或“提高 IRQL”,它会完全阻止线程调度。
自旋锁最终允许内核避免“大内核锁”(内核进入内核时获取并在退出时释放的锁)并对内核原语进行粒度锁定,从而在多核机器上实现更好的多处理,从而获得更好的性能.
编辑:出现了一个问题:“这是否意味着我应该尽可能使用自旋锁?”我会尽力回答:
正如我所提到的,自旋锁仅在预期等待时间短于时间量(读取:毫秒)并且抢占没有多大意义(例如内核对象不可用)的地方有用。
如果等待时间未知,或者您处于用户模式,则自旋锁效率不高。在检查自旋锁是否可用时,您在等待内核上消耗了 100% 的 CPU 时间。您阻止其他线程在该核心上运行,直到您的量程到期。这种情况仅适用于内核级别的短时间突发,不太可能是用户模式应用程序的选项。
这是一个关于 SO 的问题:Spinlocks, How Useful Are They?
【讨论】:
假设一个资源被一个锁保护,一个想要访问该资源的线程需要首先获取锁。如果锁不可用,线程可能会反复检查锁是否已被释放。在此期间,线程忙于等待,检查锁,使用 CPU,但不做任何有用的工作。这种锁称为自旋锁。
【讨论】:
这几乎是一个循环,直到满足某个条件:
while(cantGoOn) {};
【讨论】:
sleep(0),它会抢占线程,首先杀死使用自旋锁的目的。如果您需要让步给其他线程,您应该使用常规锁。 (我知道您的评论已经很老了,但想阻止其他人将此视为建议)。
while(something != TRUE ){};
// it happend
move_on();
【讨论】:
这是一种锁定busy waiting
它被认为是一种反模式,除了非常低级的驱动程序编程(调用“适当的”等待函数可能比简单地忙锁定几个周期有更多的开销)。
【讨论】:
自旋锁是线程等待锁可用的锁。这通常用于避免在某个小时间段内存在获取内核对象的范围时获取内核对象的开销。
例如:
While(SpinCount-- && Kernel Object is not free)
{}
try acquiring Kernel object
【讨论】:
当您认为进入繁忙的等待循环并池化资源而不是在资源被锁定时阻塞时更便宜时,您会想要使用自旋锁。
当锁的粒度很细且数量很大(例如,链表中的每个节点一个锁)以及锁保持时间总是极短时,自旋可能会很有用。一般来说,当持有自旋锁时,应该避免阻塞,调用任何本身可能阻塞的东西,一次持有多个自旋锁,进行动态调度调用(接口和虚拟),对任何代码进行静态调度调用t 拥有或分配内存。
还需要注意的是,出于性能原因,SpinLock 是一种值类型。因此,必须非常小心不要意外复制 SpinLock 实例,因为这两个实例(原始实例和副本)将完全相互独立,这可能会导致应用程序的错误行为。如果 SpinLock 实例必须被传递,它应该通过引用而不是值传递。
【讨论】:
这是一个循环,直到满足条件。
【讨论】:
简而言之,spinlock 使用原子比较和交换 (CAS) 或类似测试和设置的指令来实现无锁、无等待线程安全习语。这种结构在多核机器中可以很好地扩展。
【讨论】:
嗯,是的 - 自旋锁(与传统的临界区等相比)的关键在于它们在某些情况下(多核系统......)提供更好的性能,因为它们不会立即产生线程的其余部分.
【讨论】:
自旋锁,是一种锁,不可阻塞且不可休眠。任何想要为任何共享或关键资源获取自旋锁的线程都将持续自旋,浪费 CPU 处理周期,直到它获取指定资源的锁为止。一旦获得自旋锁,它会尝试在其量程内完成工作,然后分别释放资源。自旋锁是优先级最高的一种锁,简单来说,它是一种非抢占式的锁。
【讨论】: