Niepowodzenie synchronizacji stylu Dekkera zwykle tłumaczy się przez zmianę kolejności instrukcji. To znaczy, jeśli piszemyDlaczego nie ma wystarczającej ilości C++ 11 fence_release do synchronizacji Dekkera?
atomic_int X;
atomic_int Y;
int r1, r2;
static void t1() {
X.store(1, std::memory_order_relaxed)
r1 = Y.load(std::memory_order_relaxed);
}
static void t2() {
Y.store(1, std::memory_order_relaxed)
r2 = X.load(std::memory_order_relaxed);
}
Następnie ładunki mogą być zreorganizowane ze sklepów, co prowadzi do r1==r2==0
.
Spodziewałem ogrodzenie acquire_release aby zapobiec tego rodzaju zmiany kolejności:
static void t1() {
X.store(1, std::memory_order_relaxed);
atomic_thread_fence(std::memory_order_acq_rel);
r1 = Y.load(std::memory_order_relaxed);
}
static void t2() {
Y.store(1, std::memory_order_relaxed);
atomic_thread_fence(std::memory_order_acq_rel);
r2 = X.load(std::memory_order_relaxed);
}
Ładunek nie może zostać przeniesiony nad ogrodzeniem i magazyn nie może być przeniesiona pod ogrodzeniem, a więc zły wynik należy zapobiegać .
Jednak eksperymenty pokazują, że nadal może występować r1==r2==0
. Czy jest to uzasadnione na nowo? Gdzie jest wada mojego rozumowania?