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
?
Is it possible for 2 distinct threads to receive the same x_old value of 0?
It is not possible because the operation is atomic. It either happens in full, or not happen at all.
Ordering is concerned with preceding/following loads/stores and since you do not have any, ordering is irrelevant here. In other words, x.fetch_add(1, std::memory_order_relaxed);
has the same effect here.
On current x86 is it the same lock xadd
instruction regardless of memory_order
, lock
prefix provides both atomicity and ordering. For memory_order_relaxed
the ordering part of lock
is unnecessary.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With