Beware, your code is probably not doing what you intended it to do.
Acquire and Release pertain to guarantees about re-ordering with respect to the following and the preceding reads/writes. Nothing guarantees that another thread doesn't jump in and do its own write in the meantime. For instance, if you compile this code on x86/x64, it will emit regular movs, which already have acq/rel semantics. But they still don't guarantee atomicity – you can trivially have a race condition. FWIW, using SeqCst wouldn't help here, either, for the same reason.
The following code (Playground) demonstrates this problem by triggering an assertion failure:
fn racy() {
for _ in 0..1_000_000 {
let x1 = X.load(SeqCst);
let x2 = X.load(SeqCst);
assert_eq!(x1, x2);
X.store(x2 + 1, SeqCst);
}
}
fn main() {
let t1 = thread::spawn(racy);
let t2 = thread::spawn(racy);
println!("{:?}", t1.join());
println!("{:?}", t2.join());
}