Search code examples
c++multithreadingc++11memory-modelstdatomic

Atomic values modification in relaxed order


Assume I have the following code snippet:

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();
}

The question is: can I obtain 0 0 as a result?

Here both threads read and modify a in a relaxed memory order, so it seems that both of them can see the zero value of a. But in practice I see only 0 1 or 1 0.


Solution

  • No, 0 0 is not possible. A relaxed memory order doesn't mean the operations aren't atomic, and the only way for 0 0 to occur is for the read-modify-writes to be non-atomic. But since std::atomic::fetch_add operates atomically, we know that only one fetch_add may be operating at a time, so only 0 1 or 1 0 are possible.