gpt4 book ai didi

language-agnostic - 自旋锁是如何在底层实现的?

转载 作者:行者123 更新时间:2023-12-04 09:00:49 25 4
gpt4 key购买 nike

This is a lock that can be held by only one thread of execution at a time. An attempt to acquire the lock by another thread of execution makes the latter loop until the lock is released.

当两个线程试图同时获取锁时如何处理?

我认为这个问题也适用于其他各种互斥锁实现。

最佳答案

如上一张海报所示,每一种现代机器类型都有一种特殊的指令类别,称为“原子”,它们的运行方式与上一张海报所指的一样……它们至少针对指定的内存位置序列化执行。

在 x86 上,有一个 LOCK 汇编器前缀,指示机器应该以原子方式处理下一条指令。当遇到指令时,x86 上会发生几件事情。

  1. 挂起的读取预取被取消(这意味着 CPU 不会向程序提供可能在原子范围内变得陈旧的数据)。
  2. 对内存的挂起写入被刷新。
  3. 操作以原子方式执行、保证并针对其他 CPU 进行序列化。在这种情况下,“序列化”意味着“它们一次发生一个”。原子的意思是“这条指令的所有部分都在没有其他任何干预的情况下发生”。

对于 x86,有两个常用的指令用于实现锁。

  1. CMPXCHG。有条件的交换。伪代码:
uint32 cmpxchg(uint32 *memory_location, uint32 old_value, uint32 new_value) {    atomically {        if (*memory_location == old_value)             *memory_location = new_value;        return old_value;    }}
  1. XCHG。伪代码:
uint32 xchg(uint32 *memory_location, uint32 new_value) {    atomically {        uint32 old_value = *memory_location;        *memory_location = new_value;        return *old_value;    }}

所以,你可以像这样实现一个锁:

uint32 mylock = 0;while (cmpxchg(&mylock, 0, 1) != 0)    ;

我们自旋,等待锁,因此,自旋锁。

现在,解锁的指令不会表现出这些好的行为。根据您使用的机器,使用未锁定的指令,可以观察到各种违反一致性的行为。例如,即使在具有非常友好的内存一致性模型的 x86 上,也可以观察到以下情况:

    Thread 1      Thread 2    mov [w], 0    mov [x], 0    mov [w], 1    mov [x], 2    mov eax, w    mov eax, x    mov [y], eax  mov [z], eax

在这个程序结束时,y 和 z 的值都可以是 0!

无论如何,最后一点:x86 上的 LOCK 可以应用于 ADD、OR 和 AND,以便为指令获得一致的原子读-修改-写语义。例如,这对于设置标志变量并确保它们不会丢失很重要。没有它,你就会遇到这个问题:

   Thread 1       Thread 2   AND [x], 0x1   AND [x], 0x2

在这个程序结束时,x 的可能值是 1、2 和 0x1|0x2 (3)。为了获得正确的程序,您需要:

   Thread 1           Thread 2   LOCK AND [x], 0x1  LOCK AND [x], 0x2

希望这会有所帮助。

关于language-agnostic - 自旋锁是如何在底层实现的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2891928/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com