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