Reputation: 17223
I was going over the boost Atomic documentation and I came across the following example:
atomic<int> a(0);
thread1:
... /* A */
a.fetch_add(1, memory_order_release);
thread2:
int tmp = a.load(memory_order_acquire);
if (tmp == 1)
{
... /* B */
}
else
{
... /* C */
}
Now I am still a bit confused regarding memory_order_release and memory_order_acquire .The documentation describes them as:
memory_order_release
Perform release operation. Informally speaking, prevents all preceding memory operations to be reordered past this point.
memory_order_acquire
Perform acquire operation. Informally speaking, prevents succeeding memory operations to be reordered before this point.
Even with these examples I am still a bit confused. I would appreciate it if someone could explain what the above definitions mean and also how can A and C be in conflict ?
Upvotes: 2
Views: 1093
Reputation: 208323
The definitions mean that none of the memory operation in A can be reordered after the store to a
(definition of release in the question). And that none of the operations in B or C can precede the load of a
in the other thread (definition of acquire in the question).
Now, the example is assuming that there is no other code that operates on a
, or at least that writes to a
. If B is executed, it means that a
had the value 1 when the load into tmp
happened. For a
to have value 1, the fetch_add
had to be executed before (the fetch_add
synchronizes with the load
), which means that the code in A completed execution. If that particular code path is hit, the ordering of the operations is:
A
a.fetch_add(1,memory_order_release);
int tmp = a.load(memory_order_acquire);
B
Now the other options is that when the load
happens the value is still 0. That implies that the first thread did not get to execute the fetch_add
, but there is no guarantee as of where it might be executing. By the time that thread 2 executes C, A might still be executing (or it might have not even started, or it might have completed).
If both A and B access the same variable, there is no conflict, because the atomic guarantees that B can only be executed after A has already completed. On the other hand, that guarantee is not given for C, so if A and C touch the same variable and at least one of them writes to it, then there is a race condition.
Upvotes: 2