the memory_order enumeration
/ memory_order -> MEM-ree OR-der /
When you do an atomic operation, you are also making a second, separate choice: how much surrounding memory traffic must this operation pin in place? The memory_order enumeration is the small menu of answers. It lets you pay only for the ordering strength you actually need, because stronger ordering can cost real CPU cycles and barriers.
The six values, from strongest to weakest, are: memory_order_seq_cst (the default — a single global order everyone agrees on), memory_order_acq_rel (for read-modify-write ops: an acquire on the load side and a release on the store side), memory_order_acquire (a load that no later read/write may float above), memory_order_release (a store that no earlier read/write may float below), memory_order_consume (a discouraged, weaker cousin of acquire that follows only data dependencies), and memory_order_relaxed (atomic but with no ordering guarantees at all beyond the single location's own modification order). In Rust the equivalent enum is std::sync::atomic::Ordering with variants SeqCst, AcqRel, Acquire, Release, and Relaxed (Rust deliberately omits Consume).
The practical advice is honest and blunt: start with seq_cst everywhere. It is the easiest to reason about and is correct by default. Only weaken an ordering after you have measured a real bottleneck and can argue, on the happens-before relation, that the weaker order is still correct. Most relaxed/acquire/release bugs come from programmers reaching for speed they did not need and breaking an invariant they did not realize they relied on.
atomic_store_explicit(&p, ptr, memory_order_release); /* writer */ T *q = atomic_load_explicit(&p, memory_order_acquire); /* reader */ /* the release/acquire pair makes everything the writer did before the store visible to the reader after the load */
The release/acquire pairing is the workhorse: cheaper than seq_cst, strong enough to safely hand data between two threads.
An ordering tag is only meaningful in PAIRS across threads — a lone release with no matching acquire (or vice versa) synchronizes nothing; the tags describe a relationship, not a property of one access.