Question

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 ?

Was it helpful?

Solution

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top