Search code examples
c++multithreadingmemory-model

What's the difference between atomic.store and atomic_thread_fence?


I've been asked about the differences between these two functions of f and g:

atomic<int> var(1);
int a = 1;

void f() {
 a=123;
 var.store(0, std::memory_order_release);
}

void g() {
 a=123;
 std::atomic_thread_fence(std::memory_order_release);
 var.store(0, std::memory_order_relaxed);
}

In my opinion they have same effects, because if other threads read var=0 we can be sure that a=123, right?


Solution

  • Both functions f() and g() are a correct implementation of release logic and behave the same.

    Whether other threads read a==123 if var==0 depends on whether the data was acquired:

    if (var.load(std::memory_order_acquire) == 0)
    {
        assert(a==123);
    }
    

    Or:

    if (var.load(std::memory_order_relaxed) == 0)
    {
        std::atomic_thread_fence(std::memory_order_acquire);
        assert(a==123);
    }
    

    Both asserts cannot fire