I am trying to learn about execution order involving atomic variables in C++, and I have the following code.
According to cppreference, I have the following reasoning:
-
C++ enforce 1->2 order when executing Because no load/store can be moved before an acquire-load within the same thread.
-
C++ enforce 3->4 order when executing The same reason as 1
-
C++ enforce 2->3 order when executing
Because 2 is a release-store to y, and 3 is an acquire-load from y. So 2 should be visible to 3. Thus, 2 should be executed before 3, and 3 will read the result of 2's write.
-
C++ enforce 4->1 order when executing The same reason as 3
From reasoning 1/2/3, we can deduce a execution order of 1 -> 2 -> 3 -> 4
, and it will break reasoning 4. From reasoning 1/2/4, we can deduce a execution order of 3 -> 4 -> 1 -> 2
, and it will break reasoning 3.
Seems there are conflicts here.
int main() {
while(true) {
std::atomic<int> x, y;
x.store(10);
y.store(20);
auto f1 = [&]() {
int r1 = x.load(std::memory_order_acquire); // 1
y.store(r1, std::memory_order_release); // 2
};
auto f2 = [&]() {
int r2 = y.load(std::memory_order_acquire); // 3
x.store(r2, std::memory_order_release); // 4
};
std::thread t1(f1);
std::thread t2(f2);
t1.join();
t2.join();
printf("%d %d\n", x.load(), y.load());
}
}
-- EDIT --
My reasoning about why 2 must happens before 3:
- From preshing, y.store(rel) syncs-with y.load(acq).
- Then according to cppreference, we can have y.store(rel) Inter-thread happens-before y.load(acq).
- Then y.store(rel) happens-before y.load(acq).
- So y.store(rel) must happens before y.load(acq)
Aucun commentaire:
Enregistrer un commentaire