[Day26] Read Rust Atomics and Locks - Fences
by Mara Bos
At Topic: Chapter 3. Memory Ordering, Fences
Recall
When working with atomics (mutating data that's shared between threads), we have to explicitly tell the compiler and processor what they can and can't do with our atomic operations by the std::sync::atomic::Ordering
enum.
Which are:
- Relaxed ordering:
Ordering::Relaxed
- Release and acquire ordering:
Ordering::{Release, Acquire, AcqRel}
- Sequentially consistent ordering:
Ordering::SeqCst
Notes
-
In addition to memory operations on atomic variables, memory ordering can also be applied to "atomic fences" in concurrent programming
-
std::sync::atomic::fence
-
Four types: release fence (Release), acquire fence (Acquire), AcqRel or SeqCst
-
An atomic fence allows you to separate the memory ordering from the atomic operation:
a.store(1, Release); // is equal to fence(Release); a.store(1, Relaxed); // and a.load(Acquire); // is equal to a.load(Relaxed); fence(Acquire); // Benefit: apply a memory ordering to multiple operations, conditionally use cases etc.
-
Using a separate fence can result in an extra processor instruction, though, which can be slightly less efficient.
-
A fence is not tied to any single atomic variable => a single fence can be used for multiple variables at once.
-
By using fence conditionally, we can avoid unnecessary memory ordering and optimize performance
-
A
SeqCst
andAcqRel
fence cannot be split into a relaxed operation and a memory fence