Atomic operations on a single variable

254 views Asked by At

What are the possible final results for the variable x in the following C++ code fragment? (please answer based on what is allowed by the C++ standard and not what is currently available on different platforms)

// Inside Thread 0
std::atomic<int> x = {2};
// Inside Thread 1
x.fetch_sub(1,std::memory_order_relaxed)
// Inside Thread 2
x.fetch_sub(1,std::memory_order_relaxed)

Ideally I want x to be zero at the end. Is that the case, eventhough I am using std::memory_order_relaxed?

Edit: To make the question more precise, is it guaranteed that 1) In Threads 1 and 2 the return value is either 0 or 1, and 2) The return value in Threads 1 and 2 are different.

1

There are 1 answers

0
Fureeish On BEST ANSWER

Short answer: Yes.

Long answer: std::memory_order_relaxed is described as:

Relaxed operation: there are no synchronization or ordering constraints imposed on other reads or writes, only this operation's atomicity is guaranteed.

Source

What this effectively means is that it only guarantees atomicity. That means that the std::atomic::fetch_sub operation will guarantee just the atomic read-modify-write operation, no ordering whatsoever regarding other operations. This, however, does not mean that the compiler may reorder two different atomic read, modify and write operations (that could lead to data race, which is Undefined Behaviour). They are still atomic.

Ideally I want x to be zero at the end. Is that the case, eventhough I am using std::memory_order_relaxed?

Memory order won't matter in this case. None of them will interfere with basic guarantees of atomicity. The above statement you made will hold true for any memory order, because it holds true, by definition, for any atomic variable which is modified in such manner (two, potentially asynchronous, subtractions from the initial value of 2).

To make the question more precise, is it guaranteed that 1) In both threads the return value is either 0 or 1, and 2) The return value in Threads 1 and 2 are different.

Yes and yes, assuming that threads return the value that x holds just after the fetch_sub call, which is probably technically incorrect (threads don't return values), but I see where you are coming from here.