Consider an
std::atomic<int> x(0);
Let's suppose I have a function doing the following:
int x_old = x.fetch_add(1,std::memory_order_acq_rel);
Based on the description for acquire release memory ordering:
memory_order_relaxed Relaxed operation: there are no synchronization or ordering constraints, only atomicity is required of this operation (see Relaxed ordering below)
memory_order_consume A load operation with this memory order performs a consume operation on the affected memory location: no reads or writes in the current thread dependent on the value currently loaded can be reordered before this load. Writes to data-dependent variables in other threads that release the same atomic variable are visible in the current thread. On most platforms, this affects compiler optimizations only (see Release-Consume ordering below)
memory_order_acquire A load operation with this memory order performs the acquire operation on the affected memory location: no reads or writes in the current thread can be reordered before this load. All writes in other threads that release the same atomic variable are visible in the current thread (see Release-Acquire ordering below)
memory_order_release A store operation with this memory order performs the release operation: no reads or writes in the current thread can be reordered after this store. All writes in the current thread are visible in other threads that acquire the same atomic variable (see Release-Acquire ordering below) and writes that carry a dependency into the atomic variable become visible in other threads that consume the same atomic (see Release-Consume ordering below).
memory_order_acq_rel A read-modify-write operation with this memory order is both an acquire operation and a release operation. No memory reads or writes in the current thread can be reordered before or after this store. All writes in other threads that release the same atomic variable are visible before the modification and the modification is visible in other threads that acquire the same atomic variable.
memory_order_seq_cst Any operation with this memory order is both an acquire operation and a release operation, plus a single total order exists in which all threads observe all modifications in the same order (see Sequentially-consistent ordering below)
Is it possible for 2 distinct threads to receive the same x_old
value of 0? Or are they guaranteed to execute in a manner that x_old
is 0 for only one of them, and is 1 for the other.
If it is true that x_old
could be 0 for both of them, does changing the memory ordering to std::memory_order_seq_cst
guarantee uniqueness of x_old
?
memory_order_seq_cst
Any operation with this memory order is both an acquire operation and a release operation" It isn't precisely true. Any operation that wouldn't accept either mo_acquire or mo_release (because it either doesn't observe a value or doesn't modify a value) is not magically made an acquire or a release operation by virtue of beingmemory_order_seq_cst
. – Angarsk