Saltar a contenido

Week 9 - Threading, Send, Sync, and the Memory Model

9.1 Conceptual Core

  • Send = "safe to transfer ownership to another thread."
  • Sync = "safe to share by &T across threads" (equivalently: &T: Send).
  • These are auto traits: structurally derived. A struct is Send if all its fields are Send, etc. Opt-out by including a PhantomData<*const ()> or by using !Send/!Sync negative impls (nightly).
  • Memory model: Rust's memory model is, today, the C++20 memory model (consume order excluded). You must internalize the happens-before relation, the meaning of Relaxed, Acquire, Release, AcqRel, SeqCst, and the difference between synchronization and visibility.

9.2 Mechanical Detail

  • std::thread::spawn vs thread::scope: scoped threads (stable since 1.63) allow borrowing from the parent stack frame because the join is guaranteed before the borrow ends. This is the right default for most parallelism.
  • Atomics (AtomicUsize, AtomicPtr<T>, AtomicBool, etc.): the API surface is small but every method takes an Ordering. The orderings are:
  • Relaxed-no synchronization; only atomicity. Used for counters where ordering doesn't matter (e.g., metrics).
  • Acquire / Release-pairwise synchronization. A Release store synchronizes with an Acquire load that observes the value, establishing happens-before from the store-side's prior writes to the load-side's subsequent reads.
  • AcqRel-both, on RMW (read-modify-write) operations.
  • SeqCst-total order across all SeqCst operations system-wide. Strongest, slowest, safest if you do not yet know what you're doing.
  • fence: standalone memory barriers. Rarely needed; usually a smell that the abstraction should be different.
  • Spin loops: std::hint::spin_loop() emits pause (x86) / yield (ARM). Critical for short-wait spinlocks; missing this hint hurts SMT performance and burns power.

9.3 Lab-"A Correct Spinlock"

Implement Spinlock<T> from scratch using AtomicBool: - lock() spins with Relaxed load, then Acquire CAS. - unlock() Release stores false. - Returns a SpinlockGuard<'_, T> whose Drop unlocks. - Verify with loom (run all interleavings-see week 10) that no two threads enter the critical section.

9.4 Idiomatic & Clippy Drill

  • clippy::mutex_atomic, clippy::mutex_integer, clippy::needless_collect, clippy::should_implement_trait. The first two flag the anti-pattern of Mutex<bool> where AtomicBool suffices.

9.5 Production Hardening Slice

  • Add a loom feature gate to your spinlock crate. Run cargo test --features loom in CI. Fail the build on any model-checker violation.

Comments