Synchronization via compare_exchange failure
⚓ Rust 📅 2026-06-09 👤 surdeus 👁️ 2I'm wondering what level of synchronization the failure case of compare_exchange provides
static mut VALUE: u64 = 0;
pub fn some_func() {
let flag = Arc::new(AtomicBool::new(false));
let flag1 = flag.clone();
let flag2 = flag.clone();
let h1 = thread::spawn(move || thread_a_runner(&flag1));
let h2 = thread::spawn(move || thread_b_runner(&flag2));
h1.join().unwrap();
let result = h2.join().unwrap();
assert_ne!(0, result);
}
fn thread_a_runner(flag: &AtomicBool) {
unsafe { VALUE = 1 }
flag.store(true, Ordering::Release);
}
fn thread_b_runner(flag: &AtomicBool) -> u64 {
std::thread::sleep(Duration::from_nanos(100));
let mut value = 2;
if flag
.compare_exchange(false, false, Ordering::Relaxed, Ordering::Acquire)
.is_err()
{
unsafe {
value = VALUE;
}
}
value
}
In this code, does the failure ordering of the compare_exchange synchronize with the store and therefore ensure that VALUE is set to 1 (if the timing is right and the failure actually occurs)?
If thread B sleeps long enough to have thread A finish and then also observes the change of the flag, the compare_exchange should fail, in which case the if-block is entered. Because the failure case uses acquire ordering and the storing uses release ordering, I would assume that VALUE is therefore always 1 if the if-block is entered.
(This is obviously in no way sensible code to write but it was the quickest example I could come up with to illustrate the question)
2 posts - 2 participants
🏷️ Rust_feed