Synchronization Primitives • Compare-and-Swap & Atomic OperationsMedium⏱️ ~2 min
Other Atomic Operations
Key Insight
Hardware provides several atomic operations beyond CAS. Each has specific use cases where it is simpler or more efficient.
Common Atomic Operations
fetch_add (and fetch_sub)
Adds to a value and returns the old value. Perfect for counters. No CAS loop needed. Simpler and often faster than CAS for increments.
exchange
Unconditionally swaps a new value in and returns the old value. Useful for spinlocks: exchange 1 in, if you get 0 back, you got the lock.
test_and_set
Special case of exchange where new value is always 1. Classic spinlock primitive. Return value tells if you were first (got 0) or someone beat you (got 1).
When To Use Which
Counters: fetch_add (no loop)
Spinlocks: test_and_set or exchange
Complex updates: CAS loop
Flags: fetch_or to set, fetch_and to clear
Rule: Use the simplest operation that solves your problem. CAS is powerful but often overkill.
💡 Key Takeaways
✓Fetch-and-Add: atomically add and return old value. Simpler than CAS for counters.
✓Test-and-Set: set to 1, return old. Old == 0 means you acquired the lock.
✓Exchange: swap unconditionally. Useful for pointer updates where old value is needed.
✓LL/SC (Load-Linked/Store-Conditional): ARM alternative to CAS. SC fails if location changed since LL.
✓Choose the right primitive: CAS for conditional updates, fetch-and-add for counters, TAS for simple locks.
📌 Examples
1Fetch-and-add counter: count = atomic_fetch_add(&counter, 1); // returns value before add
2Spinlock acquire: while (atomic_exchange(&lock, 1) == 1) { /* spin */ }