Say we have two global variables:
constinit int x = 0;
std::atomic_int i = 0;
Furthermore, we have two threads A
and B
that concurrently do the following:
// thread A
x = 1;
i.store(1, std::memory_order::relase);
// thread B
i.load(std::memory_order::acquire);
x = 2;
Intuitively, this is a data race because x = 1
and x = 2
can happen at the same time.
There is no mutex, no if statement, no nothing that would prevent x = 1
and x = 2
from being done simultaneously.
You can’t just dump a random ignored load
somewhere and expect this to get rid of data races.
However, based on my reading of the standard, this is not a data race!
x = 1
happens before x = 2
because:
i.store(1, std::memory_order::release)
synchronizes withi.load(std::memory_order::acquire);
because any release operation synchronizes with any load operation on the same atomic object ([atomics.order] p2).- The
load
inter-thread happens beforex = 2
because theload
synchronizes with thestore
and thestore
is sequenced beforex = 2
([intro.races] p9.3.1). x = 1
inter-thread happens beforex = 2
becausex = 1
is sequenced before theload
and theload
inter-thread happens beforex = 2
([intro.races] p9.3.2).
Because x = 1
happens before x = 2
, there is no data race.
Furthermore, since x = 1
and x = 2
are the only modifications of x
(after initialization) and because x = 1
is a visible side effect by definition, thread B
would be guaranteed to obtain the value 1
for x
if it was to read it instead of writing to it.
Obviously, I mist be missing something. But what am I missing?
Maybe this is also a defect. [intro.races] p14 says that:
The value of an atomic object M, as determined by evaluation B, is the value stored by some unspecified side effect A that modifies M, where B does not happen before A.
This “unspecified” makes it so that even if a store
synchronizes with a load
, that load
can obtain a value from an unspecified prior side effect.
However, regardless of whether it is executed after, the load
is said to happen after the store
, which brings some thread safety where it seemingly should not.