While trying to understand memory orders I stumbled upon this video. The video claims that the assertion at the end of the main function may fail, but I do not understand why or if this is correct.
What I understand from std::memory_order_release is that no reads or writes in the current thread can be re-ordererd after this store. And for std::memory_order_acquire no reads or writes in the current thread can be re-ordered before this load. But for each reading thread in the example given there is a wait for a different writer thread, and the if from a reading thread cannot be re-ordered before the while, because of the std::memory_order_acquire. So, shouldn't at least one thread increment the z variable?
#include <atomic>
#include <thread>
#include <memory>
#include <cassert>
std::atomic<bool> x;
std::atomic<bool> y;
std::atomic<int> z;
void write_x() {
  x.store(true, std::memory_order_release);
}
void write_y() {
  y.store(true, std::memory_order_release);
}
void read_x_then_y() {
  while (!x.load(std::memory_order_acquire));
  if (y.load(std::memory_order_acquire)) {
    z++;
  }
}
void read_y_then_x() {
  while (!y.load(std::memory_order_acquire));
  if (x.load(std::memory_order_acquire)) {
    z++;
  }
}
int main() {
  x = false;
  y = false;
  z = 0;
  std::thread a(write_x);
  std::thread b(write_y);
  std::thread c(read_x_then_y);
  std::thread d(read_y_then_x);
  a.join();
  b.join();
  c.join();
  d.join();
  assert(z != 0);
  return 0;
}
Compiled with CPPFLAGS="-latomic -pthread" make main
Aucun commentaire:
Enregistrer un commentaire