I used loom
to check this, and it passed. However, I don't know why it works
use loom::sync::atomic::{AtomicBool, Ordering};
use loom::sync::{Arc, Condvar, Mutex};
use loom::thread;
fn main() {
loom::model(|| {
let x = Arc::new(AtomicBool::new(false));
let x1 = x.clone();
let x2 = x.clone();
let lock = Arc::new(Mutex::new(false));
let lock1 = lock.clone();
// cvar is used just to ensure thread1 do things first.
let cvar = Arc::new(Condvar::new());
let cvar1 = cvar.clone();
let jh1 = thread::spawn(move || {
let mut guard = lock.lock().unwrap();
x1.store(true, Ordering::Relaxed); // ???
*guard = true;
cvar.notify_one();
// drop guard, the thread2 continues to work
});
let jh2 = thread::spawn(move || {
// if thread2 got the lock first, then give it out to thread1
let mut guard = lock1.lock().unwrap();
while !*guard {
guard = cvar1.wait(guard).unwrap();
}
let x = x2.load(Ordering::Relaxed); // ???
assert!(x);
});
jh1.join().unwrap();
jh2.join().unwrap();
});
}
What confused me a lot is:
- thread1 stores x in
Ordering::Relaxed
- thread2 loads x in
Ordering::Relaxed
- Although Mutex is used to ensure thread2 continues after thread1, no
Ordering::Acquire
norOrdering::Release
exists, why the storing (thread1) is guaranteed to be seen by the loading(thread2)?
Edit: fix some grammer mistakes