我们假设我有以下代码(玩具示例):
std::atomic<K *> data;
K *old_value = NULL;
K *new_value = new K();
if (!data.compare_exchange_strong(old_value, new_value, m1, m2)) {
delete new_value;
}
do_something(old_value);
或者
std::atomic<K *> data;
K *i = data.load(m3);
K *j;
do {
j = i + 1;
} while (data.compare_exchange_weak(i, j, m4, m5);
do_something(j);
m1
,m2
,m3
,m4
和m5
的有效值是多少?
我的阅读是所有都可以std::memory_order_relaxed
,因为整个代码强烈依赖于先前操作的结果(假设do_something
只使用指针而不改变全局共享状态)。我的阅读是否正确?
答案 0 :(得分:4)
这个问题仅在具有明确定义的共享状态的多线程场景中才有意义。在不知道其他线程做什么的情况下,我只能假设它读/写data
。只需要这个单一的同步点,所有宽松的排序应该可以。对于任何独立于其他同步点考虑的给定原子,操作仍然是原子的,它们的相对顺序仍然是正确的。
现在,如果共享状态由几个变量组成(那就是“排序”发挥作用),那将是一个完全不同的故事;你必须担心获得/释放/等。语义。在这种情况下:
relaxed
data1
和线程2集data2
)的多个变量的更改将以相同顺序对所有其他线程可见 acquire/release
(分别在每次读/写时使用;对于不同的排序参数模式,第一项可能会变得更加宽松)
seq_cst
(再次,在每次读/写时使用):