Reputation: 1612
Apologies if this has been answered already, or if I'm missing something obvious.
I'm trying to understand how deep the guarantees of atomicity go for std::atomic
. For example, if we have
std::atomic<int> a(0);
a.store(1);
the store operation is atomic. However, what happens if we have nested atomic operations, such as this:
std::atomic<int> a(0);
std::atomic<int> b(1);
a.store(++b);
My understanding is that ++b
is atomic, and so is store()
. Am I right to assume that this is guaranteed to store 2
atomically in a
?
More importantly, if a
and b
are shared between threads T1
and T2
, is it guaranteed that a.store(++b);
performed by both threads is going to store the incremented value of b
(as seen by the respective threads) into a
atomically in each thread? In other words, can thread T2
"butt in" and increment b
once more after T1
has already incremented it once but before the result is stored into a
by T1
?
Upvotes: 0
Views: 313
Reputation: 218248
a.store(++b);
is equivalent to
int temp = ++b;
/* other threads can modify `b` but its value has been save in temp ... */
a.store(temp);
Upvotes: 1
Reputation: 275878
Atomicity does not compose.
Assuming nobody else ever writes to a
and b
and another thread tries to read both after they exist, and they read b
then a
, possible reads are exactly:
{b,a}
{1,0}
{2,0}
{2,2}
if they read a
then b
:
{a,b}
{0,1}
{0,2}
{2,2}
which in this case is the same as b
then a
.
Upvotes: 1
Reputation: 32727
The increment is atomic, and the store is atomic, but the two operations together are not. It is possible for the first thread to increment b
, get suspended, then another thread increments b
and stores that value in a
, then the first thread resumes and stores it's (now stale) value of b
into a
.
Upvotes: 2