Atomics and Concurrency
a year ago
- #Concurrency
- #Atomics
- #C++
- Atomics in C++ are operations or instructions that cannot be split or re-ordered by the compiler or CPU.
- Basic atomic operations include `store()`, `load()`, and Compare-and-Set (CAS) methods like `compare_exchange_weak()` and `compare_exchange_strong()`.
- Memory ordering is crucial in concurrent programming to prevent data races and ensure operations are executed in a predictable order.
- Three main types of memory order in C++ are relaxed (`std::memory_order_relaxed`), release-acquire (`std::memory_order_release` and `std::memory_order_acquire`), and sequentially consistent (`std::memory_order_seq_cst`).
- Relaxed memory ordering allows maximum re-ordering of instructions, while sequentially consistent provides the strongest guarantees, preventing most re-ordering.
- Release-acquire memory ordering creates synchronization points between threads, ensuring that operations before a release in one thread are visible to operations after an acquire in another thread.
- Different hardware architectures (e.g., x86 vs. ARM) have varying performance penalties for enforcing memory ordering due to their instruction set designs.
- A lock-free concurrent queue can be implemented using atomics and memory ordering, but it requires careful handling to avoid issues like the ABA problem.
- Thread Sanitizer (TSan) is a useful tool for detecting data races in concurrent code, especially when testing with different memory orderings.