Is Atomic Read-Modify-Write an Atomic or Separable Operation?
atomic read-modify-write (RMW) operations, such as x.exchange(), are atomic operations that both read and write a memory location and ensure that the read and write operations are executed in order. However, it's not explicitly defined whether these operations are considered a single atomic operation or a combination of an acquire load and a release store.
The Standard's Perspective
From the C standard's perspective, an RMW operation is considered a single operation. This is evident from the fact that it has a single name (RMW) and is referred to as a single operation by the standard. For example, [N4860](https://isocpp.org/files/papers/n4860.pdf) (Draft Working Paper std::memory_order) states:
"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."
Atomic vs. Separable Operations
The distinction between atomic and separable operations is important because it determines how other operations interact with them. If an RMW operation is treated as atomic, it means that it cannot bereordered with respect to other memory accesses. However, if it's treated as separable, it opens up the possibility of reordering between the load and store components of the operation.
Example Code
Consider the following code example, which uses x.exchange() and y.store() to set the values of two atomic variables, x and y.
std::atomic<int> x, y; void thread_A() { x.exchange(1, std::memory_order_acq_rel); y.store(1, std::memory_order_relaxed); } void thread_B() { int yy = y.load(std::memory_order_acquire); int xx = x.load(std::memory_order_acquire); std::cout << xx << ", " << yy << std::endl; }
If x.exchange() is treated as a single atomic operation, it means that the load and store components of the operation cannot be reordered. Therefore, Thread B will always observe the values of x and y to be both 1 or both 0.
However, if x.exchange() is treated as separable, it leaves open the possibility that the load and store components of the operation could be reordered. In this case, Thread B could potentially observe the values of x and y to be 0, 1, as the load from x could be reordered before the store to y.
Compiler Implementation and Standard Interpretation
Based on the standard's perspective, it would seem that Thread B should not observe 0, 1. However, the ARM64 implementation of the code suggests that the RMW operation is treated as separable, allowing for the possibility of reordering between the load and store components.
This apparent discrepancy raises the question of whether the cppreference quote is incorrect or if it's simply a misunderstanding of the standard. While it's possible that the cppreference quote is not perfectly accurate, it aligns with the standard's general treatment of RMW operations as single atomic operations.
It's important to note that the standard does not explicitly define the behavior of RMW operations under all circumstances. In particular, it does not provide clear guidance on how synchronizes-with relationships apply to RMW operations. As such, there may be room for different interpretations and implementations of RMW operations.
The above is the detailed content of Is Atomic Read-Modify-Write a Single Atomic Operation or a Separable One?. For more information, please follow other related articles on the PHP Chinese website!