Std::atomic
lastmod 2020-08-08created 2015-03-1932 edits
Memory order
- enum std::memory_order
- cppreference.com - std::memory_order 1
- Google translate en->ko: Cppreference.com_-atomic-memory_order(ko).pdf
Used as an argument to functions that conduct atomic operations to specify how other operations on different threads are synchronized.
std::memory_order specifies how regular, non-atomic memory accesses are to be ordered around an atomic operation. Absent any constraints on a multi-core system, when multiple threads simultaneously read and write to several variables, one thread can observe the values change in an order different from the order another thread wrote them. Indeed, the apparent order of changes can even differ among multiple reader threads. Some similar effects can occur even on uniprocessor systems due to compiler transformations allowed by the memory model.
The default behavior of all atomic operations in the library provides for sequentially consistent ordering (see discussion below). That default can hurt performance, but the library's atomic operations can be given an additional std::memory_order argument to specify the exact constraints, beyond atomicity, that the compiler and processor must enforce for that operation.
compare_exchange_weak & compare_exchange_strong
- MSDN: atomic::compare_exchange_strong method
- Stackoverflow: std::atomic: compare_exchange_weak vs. compare_exchange_strong
- cppreference.com: std::atomic_compare_exchange*
Compares, and applies the value if it matches.
Parameters
- expected
- Reference to the value expected to be found in the object. (i.e., the value to compare)
- desired
- The value to store if the
expectedvalue equals the value of the atomic object.
- success
- the memory synchronization ordering for the read-modify-write operation if the comparison succeeds. All values are permitted.
- failure
- the memory synchronization ordering for the load operation if the comparison fails. Cannot be std::memory_order_release or std::memory_order_acq_rel and cannot specify stronger ordering than success (until C++17)
- order
- the memory synchronization ordering for both operations
Return value
Returns true if the value was successfully changed, otherwise false.
atomic_thread_fence
- cppreference.com: std::atomic_thread_fence
- cplusplus.com: atomic_thread_fence
- MSDN: atomic_thread_fence function
Establishes memory synchronization ordering of non-atomic and relaxed atomic accesses, as instructed by order, without an associated atomic operation.
atomic_signal_fence
Establishes memory synchronization ordering of non-atomic and relaxed atomic accesses, as instructed by order, between a thread and a signal handler executed on the same thread. This is equivalent to std::atomic_thread_fence, except no CPU instructions for memory ordering are issued. Only reordering of the instructions by the compiler is suppressed as order instructs. For example, a fence with release semantics prevents reads or writes from being moved past subsequent writes and a fence with acquire semantics prevents reads or writes from being moved ahead of preceding reads.
acquire / release
atomic_bool vs atomic_flag
Correct. std::atomic may be implemented using locks.
std::atomic is atomic whether it has been implemented using locks, or without. std::atomic_flag is guaranteed to be implemented without using locks.
The primary difference besides the lock-free guarantee is:
Usually, you will want to use std::atomic<bool> when you need an atomic boolean variable. std::atomic_flag is a low level structure that can be used to implement custom atomic structures.
Troubleshooting
Does std::atomic<std::string> work appropriately?
- [Recommended] Stackoverflow: Does std::atomic<std::string> work appropriately?
- std::is_trivially_copyable
Undefined reference atomic
Passing a Trivial type above a certain size as the Atomic template argument can cause a linker error like the one below.
/tmp/cc8gyaZM.o: In function `std::atomic<A>::store(A, std::memory_order)':
dryn.cpp: (.text._ZNSt6atomicI1AE5storeES0_St12memory_order[_ZNSt6atomicI1AE5storeES0_St12memory_order]+0x3e): undefined reference to `__atomic_store_16'
Atomic API isn't complete in GCC 4.7:
When lock free instructions are not available (either through hardware or OS support) atomic operations are left as function calls to be resolved by a library. Due to time constraints and an API which is not finalized, there is no libatomic supplied with GCC 4.7. This is easily determined by encountering unsatisfied external symbols beginning with __atomic_*.
Since there is no libatomic shipped with GCC 4.7 you need to use another compiler which actually supports the features you want or provide the missing features (sample implementation).
In short, add the atomic library to the linker as shown below.
Libraries
See also
- C/C++
- Synchronization
- Multi Thread
- std::mutex
- Memory barrier
- Memory visibility
- CppMem
- MOESI protocol
- Helgrind (Valgrind)
- ABA Problem
Favorite site
- std::atomic references
- [Recommended] Sukkarak's programming stories: C++11 atomic (memory visibility and barriers) 3
- A taste of C++11 atomic objects
- Memory visibility and memory barrier
- [Recommended] Slideshare - Concurrency in action - chapter 5 (the C++ memory model and operations on atomic types) 4
- Atomic - GCC Wiki
Atomic pointer
- Stackoverflow: Atomic pointers in c++ and passing objects between threads
- Stackoverflow: Is pointer assignment atomic in C++?
- Stackoverflow: Atomic exchange of two std::atomic
objects in a lock-free manner in C++11?
How to use
- Double-Checked Locking is Fixed In C++11
- The Purpose of memory_order_consume in C++11
- The Synchronizes-With Relation
- An Introduction to Lock-Free Programming
memory order
- Stackoverflow - Difference between memory_order_consume and memory_order_acquire (CppMem)
- Stackoverflow - What do each memory_order mean?
- Stackoverflow - C++11: the difference between memory_order_relaxed and memory_order_consume
- The essentials of acquire / release fences
- SlideShare - Concurrency in action - chapter 5
- Chapter 05, The Cpp memory model and operations on atomic types