我已经阅读了C++中的std::memory_order
,并且部分理解了它。但是我仍然对它有一些疑问。
std::memory_order_acquire
的说明称,在此加载之前,当前线程中的任何读取或写入都不会被重新排序。这是否意味着编译器和CPU不允许将acquire
语句下面的任何指令移动到上面?
auto y = x.load(std::memory_order_acquire);
z = a; // is it leagal to execute loading of shared `b` above acquire? (I feel no)
b = 2; // is it leagal to execute storing of shared `a` above acquire? (I feel yes)
我可以理解为什么在acquire
之前执行负载是不合法的。但为什么存储也是不合法的呢?
- 跳过
atomic
对象中无用的负载或存储是否违法?因为它们不是volatile
,而我所知道的只有volatile
才有这个要求。
auto y = x.load(std::memory_order_acquire); // `y` is never used
return;
即使使用relaxed
内存顺序,也无法进行此优化。
- 编译器是否允许将位于
acquire
语句上方的指令移动到其下方?
z = a; // is it leagal to execute loading of shared `b` below acquire? (I feel yes)
b = 2; // is it leagal to execute storing of shared `a` below acquire? (I feel yes)
auto y = x.load(std::memory_order_acquire);
4. 在不跨越
acquire
边界的情况下,两个负载或存储操作可以重新排序吗?auto y = x.load(std::memory_order_acquire);
a = p; // can this move below the below line?
b = q; // shared `a` and `b`
同样,与“发布”语义相关的有4个疑问也有相应的疑问。
与第2和第3个问题相关,为什么没有编译器像下面的代码中g()
一样积极地优化f()
?
#include <atomic>
int a, b;
void dummy(int*);
void f(std::atomic<int> &x) {
int z;
z = a; // loading shared `a` before acquire
b = 2; // storing shared `b` before acquire
auto y = x.load(std::memory_order_acquire);
z = a; // loading shared `a` after acquire
b = 2; // storing shared `b` after acquire
dummy(&z);
}
void g(int &x) {
int z;
z = a;
b = 2;
auto y = x;
z = a;
b = 2;
dummy(&z);
}
f(std::atomic<int>&):
sub rsp, 24
mov eax, DWORD PTR a[rip]
mov DWORD PTR b[rip], 2
mov DWORD PTR [rsp+12], eax
mov eax, DWORD PTR [rdi]
lea rdi, [rsp+12]
mov DWORD PTR b[rip], 2
mov eax, DWORD PTR a[rip]
mov DWORD PTR [rsp+12], eax
call dummy(int*)
add rsp, 24
ret
g(int&):
sub rsp, 24
mov eax, DWORD PTR a[rip]
mov DWORD PTR b[rip], 2
lea rdi, [rsp+12]
mov DWORD PTR [rsp+12], eax
call dummy(int*)
add rsp, 24
ret
b:
.zero 4
a:
.zero 4
seq_cst
加载/存储,但您可能会遇到另一个线程完成写入某些内容,并通过将其释放存储到标志来发出信号的情况。 - Peter Cordesatomic
视为volatile
,在进一步处理编译器并设计防止对时序可能有问题的优化方法之前暂不进行优化:为什么编译器不合并冗余的std :: atomic写入? - Peter Cordes