我正在研究读取两个共享原子变量的多线程算法:
std::atomic<int> a(10);
std::atomic<int> b(20);
void func(int key) {
int b_local = b;
int a_local = a;
/* Some Operations on a & b*/
}
该算法的不变量是b
应该在读取a
之前读取。
问题是,编译器(比如 GCC)能否重新排序指令,以便在 b
之前读取 a
?使用显式内存栅栏可以实现这一点,但我想了解的是,两个原子负载是否可以重新排序。
此外,在了解了 Herb Sutter 的演讲(http://herbsutter.com/2013/02/11/atomic-weapons-the-c-memory-model-and-modern-hardware/)中的获取/释放语义之后,我了解到顺序一致的系统可确保获取(如加载)和释放(如存储)之间的顺序。如何在两次获取(如两次加载)之间进行排序?
编辑:添加有关代码的更多信息: 考虑两个线程 T1 和 T2 执行:
T1:读取b
的值,休眠
T2:改变a
的值,返回
T1 : 唤醒并读取a
的新值(new value)
现在,考虑重新排序的场景:
int a_local =a;
int b_local = b;
T1:读取a
的值,休眠
T2:改变a
的值,返回
T1:对 a
值的变化一无所知。
问题是“像 GCC 这样的编译器能否重新排序两个原子加载”
最佳答案
Description的 memory_order_acquire
:
no memory accesses in the current thread can be reordered before this load.
作为加载时的默认内存顺序b
是memory_order_seq_cst
,这是最强的,阅读自a
在读取 b
之前无法重新排序.
甚至更弱的内存顺序,如以下代码所示,也提供相同的保证:
int b_local = b.load(std::memory_order_acquire);
int a_local = a.load(std::memory_order_relaxed);
关于c++ - 重新排序原子读取,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34554587/