我对读取 - 修改 - 写入操作背后的机制感到困惑,例如fetch_add。当使用宽松的内存顺序时,他们如何避免读取旧值并导致结果错误?这是演示代码:
std::atomic<int> global_counter = 0;
//thread 0
int counter0 = global_counter.fetch_add(1, std::memory_order_relaxed);
assert(counter0 > 0);
//thread 1
int counter1 = global_counter.fetch_add(1, std::memory_order_relaxed);
assert(counter1 > 0);
因为两个fetch_add动作都用std :: memory_order_relaxed标记,所以只保证它们的原子性。两个线程中的fetch_add操作是否可能读取global_counter的旧值(即0),然后添加旧值?如果不是,他们如何实现这一目标?
答案 0 :(得分:1)
这是不可能的。它是通过平台特定的原子指令实现的,例如,在x86中使用'lock'前缀或在其他上使用'll / sc'。内存排序控制观察到不同内存位置的修改序列。这是原子性的一个独立问题。