intprx
intprx

Reputation: 91

Why can't you use relaxed atomic operations to synchronize memory, if there is a thread join in between?

I'm watching this Herb Sutter talk: https://channel9.msdn.com/Shows/Going+Deep/Cpp-and-Beyond-2012-Herb-Sutter-atomic-Weapons-2-of-2

Looking at two examples (around 1:15 mark), one makes sense to me and the other does not.

First example (makes sense):

Note count is an atomic int.

Here, using relaxed memory ordering for the load/store on count is said to be ok since thread exit happens before returning from a join on a thread. That means the relaxed adds happen before the relaxed load.

Child thread:

while (...) {
  if (...) {
    count.fetch_add(1, memory_order_relaxed);
  }
}

Main thread:

int main() {
  launch_workers();
  join_workers();
  cout << count.load(memory_order_relaxed);
}

Second example (unclear):

Note dirty and stop are atomic booleans.

Here, the talk says that the store and load on dirty must respectively use release and acquire ordering, since dirty is used to publish some data that is read for cleanup.

Child thread:

while(!stop.load(memory_order_relaxed)) {
  if (...) {
    // publish some data
    dirty.store(true, memory_order_release)
  }
}

Main thread:

int main() {
  launch_workers();
  stop = true;
  join_workers();
  if (dirty.load(memory_order_acquire)) {
    // read published data to clean up
  }
}

My question is, in the second example why can't you apply the same 'happens before' relationship between the thread exit and returning from a join on a thread to synchronize the memory?

The way I thought it would work with relaxed memory ordering on the operations of dirty is:

[Child thread does some work, including publishing data]

[Child thread exit] -(happens before)-> [Return from join on child thread in join_workers() call]

[Main thread both sees dirty as true and can safely read the published data to do cleanup]

Upvotes: 3

Views: 176

Answers (1)

Brian Bi
Brian Bi

Reputation: 119059

Around 1:17:25, he says "now, because you happen to know I've got a release-acquire by joining the threads, I've injected a release-acquire in there; that may be good enough and you can just go to relaxed". So he seems to be saying, in the end, that it's actually fine if dirty is accessed with relaxed memory ordering.

Upvotes: 2

Related Questions