Synchronization PrimitivesCompare-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_addold = *ptr*ptr += nreturn oldexchangeold = *ptr*ptr = newreturn oldtest_and_setold = *ptr*ptr = 1return oldload / storeAtomic read or write with memory orderingacquire, release, seq_cstfetch_or / fetch_andAtomic bitwise operationsSet/clear flags atomically

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 */ }
← Back to Compare-and-Swap & Atomic Operations Overview