【发布时间】:2021-07-01 00:51:37
【问题描述】:
在下面的代码中,对 foo 中的 a 的写入存储在存储缓冲区中,并且对 bar 中的 ra 不可见。同样,bar 中的 b 写入对 foo 中的 rb 不可见,它们打印 00。
// g++ -O2 -pthread axbx.cpp ; while [ true ]; do ./a.out | grep "00"; done prints 00 within 1min
#include<atomic>
#include<thread>
#include<cstdio>
using namespace std;
atomic<long> a,b;
long ra,rb;
void foo(){
a.store(1,memory_order_relaxed);
rb=b.load(memory_order_relaxed);
}
void bar(){
b.store(1,memory_order_relaxed);
ra=a.load(memory_order_relaxed);
}
int main(){
thread t[2]{ thread(foo),thread(bar)};
t[0].join();t[1].join();
if((ra==0) && (rb==0)) printf("00\n"); // each cpu store buffer writes not visible to other threads.
}
下面的代码与上面的代码几乎相同,只是去掉了变量 b 并且 foo 和 bar 都有相同的变量 'a' 并且返回值存储在 ra1 和 ra2 中。在这种情况下,我至少在跑步 5 分钟后不会得到“00”。
- 在第二种情况下,为什么不打印 00 ?怎么写到 x 两个线程都没有存储在 cpu 缓存中,然后打印 00 ?
- 它与 x86_64 有什么关系,但它在 arm/arm64/power 上打印 00 吗?
- 如果 arm/arm64/power 打印 00 ,存储在 foo 和 bar 之后的 smp_mb() 会修复它吗?
// g++ -O2 -pthread axbx.cpp ; while [ true ]; do ./a.out | grep "00"; done doesn't print 00 within 5 min
#include<atomic>
#include<thread>
#include<cstdio>
using namespace std;
atomic<long> a,b;
long ra1,ra2;
void foo(){
a.store(1,memory_order_relaxed);
ra1=a.load(memory_order_relaxed);
}
void bar(){
a.store(1,memory_order_relaxed);
ra2=a.load(memory_order_relaxed);
}
int main(){
thread t[2]{ thread(foo),thread(bar)};
t[0].join();t[1].join();
if((ra1==0) && (ra2==0)) printf("00\n"); // each cpu store buffer writes not visible to other threads.
}
【问题讨论】:
-
一般不要将 Linux
smp_mb()与std::atomic混合使用,只需使用atomic_thread_fence(std::memory_order_seq_cst)或任何你想要的内存顺序。
标签: c++ multithreading memory-barriers stdatomic