Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Acquire-release memory order between multiple threads

Code:

std::atomic<int> done = 0;
int a = 10;

void f1() {
  a = 20;
  done.store(1, std::memory_order_release);
}

void f2() {
  if(done.load(std::memory_order_acquired) == 1) {
    assert(a == 20);
  }
}

void f3() {
  if(done.load(std::memory_order_acquired) == 1) {
    assert(a == 20);
  }
}

int main() {
  std::thread t1(f1);
  std::thread t2(f2);
  std::thread t3(f3);
  t1.join();
  t2.join();
  t3.join();
}

The question is if thread 2 & 3 both see done == 1, will the assertion a == 20 hold in both threads ? I know acquire-release works for a pair of threads. But does it work in multiple threads as well?

like image 512
Tes Avatar asked Jul 12 '26 19:07

Tes


2 Answers

Yes. The release-acquire relationship holds separately for all pairs of threads (that access the same atomic location!) and guarantees that all writes (that appear in program order) before the release are visible to all reads (that appear in program order) after whichever corresponding acquire.

like image 173
Davis Herring Avatar answered Jul 15 '26 07:07

Davis Herring


A release is like publishing a newspaper (one with no defined periodicity), and acquire is like buying the later edition right now, then discovering what it says (not caring which edition it is, or which day it is). (You rarely need to do versioning on these shared atomics, although it can sometimes be needed.)

Any number of people can buy the newspaper. What matters is that what's printed was true when it was printed, and is still true if they are invariant truths, like the creation of a monument (invariable by hypothesis).

So a release operation publishes what is true at the time of publication, and proper design guarantees that these facts cannot have changed when you can "buy" (acquire) the publication. Any number of threads can see these facts.

like image 33
curiousguy Avatar answered Jul 15 '26 08:07

curiousguy