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.
Short answer: Yes.
Long answer:
std::memory_order_relaxed
is described as: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.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
).Yes and yes, assuming that threads return the value that
x
holds just after thefetch_sub
call, which is probably technically incorrect (threads don't return values), but I see where you are coming from here.