I'm trying to get a better understanding of atomic ordering guarantees, but this issue threw me off a bit.
In it, RalfJung and jeehoonkang are discussing this code (I changed AtomicCell to AtomicBool, hopefully that's not significant):
let x = AtomicBool::new(false);
let y = AtomicBool::new(false);
scope(|s| {
// Thread A
s.spawn(|| x.store(true, <ordering>));
// Thread B
s.spawn(|| y.store(true, <ordering>));
// Thread C
s.spawn(|| {
while !x.load(<ordering>) {}
if y.load(<ordering>) { println!("y then x"); }
});
// Thread D
s.spawn(|| {
while !y.load(<ordering>) {}
if x.load(<ordering>) { println!("x then y"); }
});
}).unwrap();
I understand that if <ordering> is replaced with Release for stores and Acquire for loads, then it is not guaranteed that this code will print anything, since thread A/B don't establish an ordering of the stores.
I have a few questions related to this code:
- If we instead use
SeqCstfor all loads and stores, is the code guaranteed to print something? - If
AtomicBoolis replaced withMutex<bool>, is it guaranteed to print? This one confused me, since in the linked issue Ralf and jeehoonkang seem to believe the answer is no. However I thought the answer was yes, since a Mutex load translates intolock(Acq); read; unlock(Rel)and I believe the Acq/Rels on every access are enough to guarantee that something prints. I'm mostly basing this intuition on this C++ SO post. - In general, if we have code that uses multiple
AtomicBoolvariables and usesSeqCstfor every access to those variables, and then we replaceAtomicBoolwithMutex<bool>, will the new code and old code have exactly the same semantics? (I'm aware that mixingSeqCstandAcq/Relcomplicates things - I'm just focusing on completelySeqCstvs completelyAcq/Relfor now)
