gpt4 book ai didi

c++ - 为什么 memory_order_relaxed 在 x86 上使用原子(锁前缀)指令?

转载 作者:塔克拉玛干 更新时间:2023-11-02 23:37:48 25 4
gpt4 key购买 nike

在 Visual C++ 2013 上,当我编译以下代码时

#include <atomic>

int main()
{
std::atomic<int> v(2);
return v.fetch_add(1, std::memory_order_relaxed);
}

我在 x86 上取回了以下程序集:

51               push        ecx  
B8 02 00 00 00 mov eax,2
8D 0C 24 lea ecx,[esp]
87 01 xchg eax,dword ptr [ecx]
B8 01 00 00 00 mov eax,1
F0 0F C1 01 lock xadd dword ptr [ecx],eax
59 pop ecx
C3 ret

在 x64 上类似:

B8 02 00 00 00    mov         eax,2 
87 44 24 08 xchg eax,dword ptr [rsp+8]
B8 01 00 00 00 mov eax,1
F0 0F C1 44 24 08 lock xadd dword ptr [rsp+8],eax
C3 ret

我根本不明白:为什么 int 变量的 relaxed 增量需要 lock 前缀?

这是有原因的,还是他们根本没有包括删除它的优化?


* 我将 /O2/NoDefaultLib 结合使用来削减它并删除不必要的 C 运行时代码,但这与问题无关。

最佳答案

因为它仍然需要锁才能成为原子;即使使用 memory_order_relaxed,递增/递减的要求也太严格而无法无锁。

想象一下没有锁的情况。

v = 0;

然后我们生成 100 个线程,每个线程使用以下命令:

v++;

然后您等待所有线程完成,您希望 v 是什么?不幸的是,它可能不是 100。假设值 v=23 由一个线程加载,在创建 24 之前,另一个线程也加载 23,然后也写出 24。所以线程实际上相互否定。这是因为增量本身不是原子的。当然,加载、存储、添加本身可能是原子的,但递增是多个步骤,因此它不是原子的。

但是对于 std::atomic,所有操作都是原子的,无论 std::memory_order 设置如何。唯一的问题是它们将以什么顺序发生。memory_order_relaxed 仍然保证原子性,它可能与附近发生的任何其他事情有关,即使是对相同的值进行操作也是如此。

关于c++ - 为什么 memory_order_relaxed 在 x86 上使用原子(锁前缀)指令?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24234769/

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