在英特尔的处理器手册:第 8.2.3.4 节中的链接中,声明可以将负载重新排序,早期存储到不同位置,但不能将早期存储重新排序到相同位置。
所以我明白以下两个操作可以重新排序:
x = 1;
y = z;
并且以下两个操作不能重新排序:
x = 1;
y = x;
但是当存储和负载位于不同的位置时会发生什么,但负载完全包含存储,例如:
typedef union {
uint64_t shared_var;
uint32_t individual_var[2];
} my_union_t;
my_union_t var;
var.shared_var = 0;
var.individual_var[1] = 1;
int y = var.shared_var;
那么在这种情况下'y'可以为0吗?
编辑(@Hans Passant)为了进一步解释这种情况,我试图看看我是否可以使用这种技术在不使用锁定指令的情况下设计一种线程之间的准同步。
所以一个更具体的问题是,给定一个全局变量:
my_union_t var;
var.shared_var = 0;
两个线程执行以下代码:
线程 1:
var.individual_var[0] = 1;
int y = __builtin_popcountl(var.shared_var);
线程 2:
var.individual_var[1] = 1;
int y = __builtin_popcountl(var.shared_var);
'y' 可以为两个线程都为 1 吗?
注意:__builtin_popcountl 是内置的 gcc 内在函数,用于计算变量中设置的位数。