以宽松的顺序修改原子值

Atomic values modification in relaxed order

假设我有以下代码片段:

std::atomic<int> a(0);

void thread1()
{
    int x = a.fetch_add(1, std::memory_order_relaxed);
    std::cout << x << std::endl;
}

void thread2()
{
    int x = a.fetch_add(1, std::memory_order_relaxed);
    std::cout << x << std::endl;
}

int main()
{
    std::thread t1(thread1);
    std::thread t2(thread2);

    t1.join();
    t2.join();
}

问题是:结果能得到0 0吗?

这里两个线程都以松散的内存顺序读取和修改a,所以看起来它们都可以看到a的零值。但实际上我只看到 0 11 0.

不,0 0 不可能。宽松的内存顺序并不意味着操作不是原子的,0 0 发生的唯一方法是读取-修改-写入是非原子的。但是由于 std::atomic::fetch_add 是原子操作的,我们知道一次只有一个 fetch_add 可能在操作,所以只有 0 11 0 是可能的。