C++ Standard Library<atomic>
In multithreaded programming, data synchronization and thread safety are important issues.
The C++11 standard introduced<atomic>The library provides a set of atomic operations to ensure that access to a single data item is atomic, i.e., indivisible, in a multithreaded environment. This can avoid data races and ensure thread safety.
Atomic operations are operations that cannot be interrupted by other threads during execution.
<atomic>The atomic types in the library provide such operations, which can ensure safe access to shared data in a multithreaded environment.
Syntax
<atomic>The library provides various atomic types, includingatomic<bool>, atomic<char>, atomic<short>, atomic<int>, atomic<long>, atomic<long long>, atomic<wchar_t>, atomic<char16_t>, atomic<char32_t>, atomic<unsigned char>, atomic<unsigned short>, atomic<unsigned>, atomic<unsigned long>, atomic<unsigned long long>, atomic<float>, atomic<double>, atomic<long double>etc.
Basic Operations
load(): safely read the value of an atomic variable.store(value): safely write a value to an atomic variable.exchange(value): replace the value of an atomic variable withvalue, and return the old value of the atomic variable.compare_exchange_weak(expected, desired): if the current value of the atomic variable equalsexpected, then set it todesired, and returnstrue. Otherwise, it willexpectedSet to the current value of the atomic variable, and return.false。compare_exchange_strong(expected, desired): andcompare_exchange_weaksimilar, but loops until successful.
Example
The following is an example using<atomic>A simple example of the library, demonstrating how to safely update a shared counter in a multi-threaded environment.
Example
#include <atomic>
#include <thread>
std::atomic<int> counter(0); // Initialize atomic counter
void increment() {
for (int i = 0; i < 10000; ++i) {
counter.fetch_add(1, std::memory_order_relaxed); // Atomic increment
}
}
int main() {
std::thread t1(increment);
std::thread t2(increment);
t1.join();
t2.join();
std::cout << "Final counter value: " << counter << std::endl; // Output the final counter value
return 0;
}
Run the above program, you will see output similar to:
Final counter value: 20000
This output shows that the two threads successfully incremented the counter value 10000 times each without data races.
Notes
- Usage
<atomic>When using the library, it is necessary to ensure that all accesses to shared data are through atomic operations to avoid data races. - Different atomic operations have different memory order requirements.
std::memory_order_relaxedIt is the lowest memory order requirement, but may not guarantee visibility of operations. Choose an appropriate memory order as needed. - The performance overhead of atomic operations is usually higher than that of non-atomic operations, so in a single-threaded environment, using ordinary variables may be more efficient.
by using<atomic>With the library, C++ programmers can more easily write thread-safe code while maintaining high performance.