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?
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