Compare and swap C0x
Interview Questions practice on Codemia
Over 8,000 real interview questions from top companies, searchable by company and role.
Introduction
Compare-and-swap, usually abbreviated as CAS, is a core atomic primitive for lock-free programming in C++11 and later. It lets a thread update shared state only if that state still equals an expected value. In modern C++ this is exposed through std::atomic and compare_exchange_weak or compare_exchange_strong.
CAS Semantics in C++11
CAS compares an atomic value with expected. If they match, it writes desired atomically and returns true. If they do not match, it writes the current atomic value back into expected and returns false.
That second behavior matters. Many bugs come from forgetting that expected is modified on failure.
Basic example:
On success, value becomes 42. On failure, expected becomes the observed value.
weak Versus strong
compare_exchange_strong fails only on genuine mismatch. compare_exchange_weak may fail spuriously, which means it can return false even when values match. Spurious failure is allowed so some architectures can generate faster instructions.
Practical rule:
- use
strongwhen attempting once - use
weakin retry loops
Typical weak loop pattern:
The loop retries until update succeeds.
Memory Ordering and CAS
CAS operations support memory order arguments. This controls visibility guarantees between threads. Many lock-free bugs come from incorrect memory ordering choices.
Common pair:
- success:
memory_order_releaseormemory_order_acq_rel - failure:
memory_order_relaxedormemory_order_acquire
For beginners, memory_order_seq_cst is simpler and safer, though potentially slower.
Use explicit orderings only when you understand the synchronization graph you need.
Lock-Free Stack Push Example
CAS is often used to update linked-list heads in lock-free structures.
This demonstrates the classic retry pattern, though full production code must also handle safe memory reclamation.
Real-World Concerns
CAS is powerful but not a universal replacement for mutexes. Under heavy contention, constant retries can waste CPU and reduce throughput. Lock-based approaches can be better for fairness or complex multi-step critical sections.
Another concern is ABA problems in pointer-based lock-free structures. A value can change from A to B and back to A, causing CAS to succeed even though intermediate state existed. Techniques such as tagged pointers or hazard pointers are used to mitigate this.
Common Pitfalls
- Forgetting that
expectedis overwritten when CAS fails. - Using
compare_exchange_weakonce without a retry loop. - Choosing memory orders inconsistently across related loads and stores.
- Assuming lock-free code is always faster under high contention.
- Ignoring ABA and reclamation issues in pointer-based designs.
Summary
- CAS atomically updates a value only when expected and current values match.
strongis for single-attempt semantics,weakis for retry loops.- Memory ordering is part of correctness, not only performance.
- CAS enables lock-free patterns but adds complexity around contention and reclamation.
- Use CAS intentionally where its trade-offs are justified.
Related reading
- Compare two MySQL databases
- CompletableFuture in loop How to collect all responses and handle errors
- CompletableFuture not working as expected
- CompletableFuture thenApply vs thenCompose
- CompletableFuture vs Async
- CompletableFuture vs Spring Transactions
- CompletableFutureT class join vs get
- Completion handlers and return values
.png&w=3840&q=75)
Tackling System Design Interview Problems
A short course that equips you with the skills to approach system design interviews methodically.
Start the free courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
Interview Questions practice on Codemia
Over 8,000 real interview questions from top companies, searchable by company and role.