samedi 17 octobre 2020

C++ memory order for consistently storing in atomic variable from multiple threads

Running the following code hundreds of times, I expected the printed value to be always 3, but it seems to be 3 only about ~75% of the time. This probably means I have a misunderstanding about the purpose of the various memory orders in C++, or the point of atomic operations. My question is: is there a way to guarantee that the output of the following program is predictable?

#include <atomic>
#include <iostream>
#include <thread>
#include <vector>

int main () {
  std::atomic<int> cnt{0};
  auto f = [&](int n) {cnt.store(n, std::memory_order_seq_cst);};

  std::vector<std::thread> v;
  for (int n = 1; n < 4; ++n)
    v.emplace_back(f, n);

  for (auto& t : v)
    t.join();

  std::cout << cnt.load() << std::endl;
  return 0;
}

For instance, here's the output statistics after 100 runs:

$ clang++ -std=c++20 -Wall foo.cpp -pthread && for i in {1..100}; do ./a.out; done | sort | uniq -c
      2 1
     21 2
     77 3

Aucun commentaire:

Enregistrer un commentaire