背景
在多线程编程中,线程间的同步和数据竞争问题是无法避免的。传统的同步方法,如互斥锁(mutex)和条件变量(condition variable),可能导致性能下降和死锁等问题。C++11引入了原子操作,提供了一种更高效、安全的多线程编程方式。本文将介绍C++中的原子操作概念、使用方法及示例。
C++中的原子操作
C++11引入了头文件,提供了一系列原子类型和操作。原子类型包括std::atomic_flag、std::atomic和特化的原子整数类型(如std::atomic_int、std::atomic_long等)。原子操作包括原子读写、原子算术运算、原子位操作等。
原子类型
(1)std::atomic_flag
std::atomic_flag是最简单的原子类型,只有两种状态:设置(set)和清除(clear)。std::atomic_flag不可拷贝和赋值,且必须使用ATOMIC_FLAG_INIT宏初始化。
#include <atomic>
std::atomic_flag flag = ATOMIC_FLAG_INIT;
(2)std::atomic
std::atomic是通用的原子类型,可以用于任何可拷贝的类型T。std::atomic的初始化可以使用默认构造函数、拷贝构造函数或者赋值操作。
#include <atomic>
std::atomic<int> atomic_int(0); // 初始化为0
3)特化的原子整数类型
特化的原子整数类型是针对整数类型的原子类型,如std::atomic_int、std::atomic_long等。它们的使用方法与std::atomic相同。
#include <atomic>
std::atomic_int atomic_int(0); // 初始化为0
原子操作
(1)原子读写 原子读写操作包括load、store和exchange。load用于读取原子变量的值,store用于设置原子变量的值,exchange用于交换原子变量的值。
#include <atomic>
#include <iostream>
int main() {
std::atomic<int> atomic_int(0);
int value = atomic_int.load(); // 读取原子变量的值
std::cout << "value: " << value << std::endl;
atomic_int.store(10); // 设置原子变量的值
std::cout << "value: " << atomic_int.load() << std::endl;
int old_value = atomic_int.exchange(20); // 交换原子变量的值
std::cout << "old_value: " << old_value << ", new_value: " << atomic_int.load() << std::endl;
return 0;
}
(2)原子算术运算
原子算术运算包括fetch_add、fetch_sub、fetch_and、fetch_or和fetch_xor等。这些操作可以实现原子加、原子减、原子与、原子或和原子异或等功能。
#include <atomic>
#include <iostream>
int main() {
std::atomic<int> atomic_int(0);
int old_value = atomic_int.fetch_add(10); // 原子加操作
std::cout << "old_value: " << old_value << ", new_value: " << atomic_int.load() << std::endl;
old_value = atomic_int.fetch_sub(5); // 原子减操作
std::cout << "old_value: " << old_value << ", new_value: " << atomic_int.load() << std::endl;
old_value = atomic_int.fetch_and(0b1100); // 原子与操作
std::cout << "old_value: " << old_value << ", new_value: " << atomic_int.load() << std::endl;
old_value = atomic_int.fetch_or(0b1010); // 原子或操作
std::cout << "old_value: " << old_value << ", new_value: " << atomic_int.load() << std::endl;
old_value = atomic_int.fetch_xor(0b1111); // 原子异或操作
std::cout << "old_value: " << old_value << ", new_value: " << atomic_int.load() << std::endl;
return 0;
}
(3)原子比较和交换
原子比较和交换操作(compare-and-swap,CAS)是一种常用的同步原语,用于实现无锁数据结构。std::atomic<T>
提供了compare_exchange_weak
和compare_exchange_strong
两个CAS操作。
#include <atomic>
#include <iostream>
int main() {
std::atomic<int> atomic_int(0);
int expected = 0;
bool success = atomic_int.compare_exchange_weak(expected, 10); // CAS操作
std::cout << "success: " << success << ", expected: " << expected << ", value: " << atomic_int.load() << std::endl;
expected = 0;
success = atomic_int.compare_exchange_strong(expected, 20); // CAS操作
std::cout << "success: " << success << ", expected: " << expected << ", value: " << atomic_int.load() << std::endl;
return 0;
}
原子操作示例
下面是一个使用原子操作实现的多线程累加器示例。在这个示例中,我们创建了两个线程,分别对原子整数变量atomic_int进行累加操作。
#include <atomic>
#include <iostream>
#include <thread>
std::atomic<int> atomic_int(0);
void add(int n) {
for (int i = 0; i < n; ++i) {
atomic_int.fetch_add(1);
}
}
int main() {
std::thread t1(add, 100000);
std::thread t2(add, 100000);
t1.join();
t2.join();
std::cout << "atomic_int: " << atomic_int.load() << std::endl;
return 0;
}
背景
通过本文的介绍,我们了解了C++中原子操作的概念、使用方法及示例。原子操作为多线程编程提供了一种高效、安全的方式,避免了传统同步方法的性能和死锁问题。在实际编程中,我们可以根据需求选择合适的原子类型和操作,实现无锁数据结构和并发算法。
标签:std,include,int,编程,C++,原子,atomic,操作,多线程 From: https://www.cnblogs.com/blizzard8204/p/17536926.html