【发布时间】:2020-04-24 17:29:49
【问题描述】:
考虑以下代码:
void add(double& a, double b) {
a += b;
}
根据godbolt 在 Skylake 上编译为:
add(double&, double):
vaddsd xmm0, xmm0, QWORD PTR [rdi]
vmovsd QWORD PTR [rdi], xmm0
ret
如果我从不同的线程调用add(a, 1.23) 和add(a, 2.34)(对于同一个变量a),a 肯定会以a+1.23、a+2.34 或a+1.23+2.34 结束吗?
也就是说,考虑到这个程序集,这些结果之一肯定会发生,a 不会以其他状态结束吗?
【问题讨论】:
-
由多个线程写入非原子变量是未定义的行为,除非您使用同步。你得到的任何结果都是“有效的”
-
@NathanOliver 但是有一个结果程序集。所以 C++ 规范在这里并不重要,不是吗?
-
是的,我特别包含了程序集,因为这就是行为 - 从 C++ 的角度来看,它可能是未定义的,但这是这个架构上的定义,带有这个 GCC 版本、标志等
-
@ThomasJohnson AFAIK,同步需要一直到 CPU。我听说 CPU 可以重新排序指令,只要它们知道它们不相互依赖。在不生成线程安全代码的情况下,您允许 CPU 破坏变量并且垃圾是有效的结果。
-
如果您不关心“C++”规范的内容,那么您应该从您的问题中删除 [C++] 标签。
标签: multithreading assembly x86-64 atomic data-race