Under The Hood
backend rust Rust 1.x (std::sync::atomic)

std::sync::atomic: Relaxed, Acquire, Release, SeqCst Memory Ordering

Last updated
Prerequisites:
Rust ownership and shared state
Understanding of the C++ memory model concepts
  • rust
  • atomics
  • memory-ordering
  • seqcst
  • acquire-release
  • concurrency

Read at your depth

The practical view

Atomic types (AtomicUsize, AtomicBool, AtomicPtr) provide lock-free operations: load, store, fetch_add, compare_exchange. The ordering parameter controls memory visibility, not atomicity (which is always guaranteed): Relaxed (no ordering constraints), Acquire (used on loads: subsequent operations can't move before it), Release (used on stores: prior operations can't move after it), AcqRel (for read-modify-write), SeqCst (strongest: a single total order). Example: atomic.load(Ordering::Acquire) after another thread's atomic.store(v, Ordering::Release) guarantees the store's prior writes are visible. Use Relaxed for counters, Acquire/Release for message passing (publish a value, then release), SeqCst when you need a global order (rare, e.g. flags that coordinate multiple threads).

The same idea in other frameworks

react equivalent
N/A — Rust concurrency feature.

Legacy vs modern

Relaxed counter vs Acquire/Release handoff

A relaxed counter is fine for stats; publishing a value with correctness requires Acquire/Release to make the data visible with the flag.

before → after
Using Relaxed for a message-publish flag
READY.store(true, Ordering::Relaxed); // ❌ OLD: flag is atomic, but data may not be visible
Release store + Acquire load
READY.store(true, Ordering::Release); // ✅ NEW: prior writes visible
READY.load(Ordering::Acquire); // ✅ NEW: sees everything before the Release

Interview gotchas

Context

This tests the fundamental model — interviewers want the hardware-instruction vs visibility distinction, because mixing them up is the most common atomics error.

The mechanical answer

Atomicity means a single operation (load, store, fetch_add, CAS) happens indivisibly — no torn reads/writes; this is guaranteed by the hardware instruction (lock-prefixed or LL/SC) regardless of the ordering parameter. Memory ordering is a SEPARATE concern: it governs how the operation's effects become visible relative to OTHER memory operations across threads. Relaxed gives atomicity but no ordering — the operation is indivisible and the value is eventually consistent, but there's no happens-before edge, so other (non-atomic) memory written before/after may not be observed in order. In safe Rust, using an Atomic (even Relaxed) cannot cause a data race on the atomic itself — the type is Send/Sync and the operation is atomic. The ordering parameter only affects visibility of surrounding memory; a Relaxed flag can still be used safely for a 'set once' signal IF no other data depends on it.

Trap

The naive answer is 'Relaxed is unsafe or buggy'. Relaxed is sound for the atomic value itself; the danger is using it to coordinate OTHER data visibility. Another trap: assuming SeqCst is always required — over-using it adds full-fence cost on weak-memory CPUs; Acquire/Release covers publish/consume patterns correctly and cheaper. Candidates who separate atomicity from ordering show real understanding.

Under The Hood — a multi-depth technical interview hub.

Third-party licenses Press ⌘ K to search.