返回
std::atomic模板特化:多线程编程的利器
后端
2024-01-09 11:50:33
概述
在多线程编程中,共享变量的访问和修改必须是原子的,否则可能会导致数据竞争和程序崩溃。为了解决这个问题,C++提供了std::atomic模板类。std::atomic是一个轻量级的原子类型,允许多个线程同时访问和修改共享变量,而不会产生数据竞争。
std::atomic的语法如下:
template<typename T>
class atomic {
public:
// 构造函数
atomic() noexcept;
atomic(T desired) noexcept;
// 赋值运算符
atomic& operator=(T desired) noexcept;
// 原子操作
T operator++() noexcept;
T operator++(int) noexcept;
T operator--() noexcept;
T operator--(int) noexcept;
// 获取和设置值
T load(memory_order order = memory_order_seq_cst) const noexcept;
void store(T desired, memory_order order = memory_order_seq_cst) noexcept;
// 比较和交换
bool compare_exchange_weak(T& expected, T desired, memory_order success_order = memory_order_seq_cst,
memory_order failure_order = memory_order_seq_cst) noexcept;
bool compare_exchange_strong(T& expected, T desired, memory_order success_order = memory_order_seq_cst,
memory_order failure_order = memory_order_seq_cst) noexcept;
// 原子交换
T exchange(T desired, memory_order order = memory_order_seq_cst) noexcept;
// 原子获取并设置
T fetch_and(T mask, memory_order order = memory_order_seq_cst) noexcept;
T fetch_or(T mask, memory_order order = memory_order_seq_cst) noexcept;
T fetch_xor(T mask, memory_order order = memory_order_seq_cst) noexcept;
T fetch_add(T value, memory_order order = memory_order_seq_cst) noexcept;
T fetch_sub(T value, memory_order order = memory_order_seq_cst) noexcept;
};
特化
std::atomic模板可以被特化为任何基本类型或用户定义类型。当std::atomic被特化时,它将生成一个新的原子类型,该类型具有与特化的类型相同的行为。
例如,以下代码将std::atomic特化为int类型:
template<>
class atomic<int> {
public:
// 构造函数
atomic() noexcept;
atomic(int desired) noexcept;
// 赋值运算符
atomic& operator=(int desired) noexcept;
// 原子操作
int operator++() noexcept;
int operator++(int) noexcept;
int operator--() noexcept;
int operator--(int) noexcept;
// 获取和设置值
int load(memory_order order = memory_order_seq_cst) const noexcept;
void store(int desired, memory_order order = memory_order_seq_cst) noexcept;
// 比较和交换
bool compare_exchange_weak(int& expected, int desired, memory_order success_order = memory_order_seq_cst,
memory_order failure_order = memory_order_seq_cst) noexcept;
bool compare_exchange_strong(int& expected, int desired, memory_order success_order = memory_order_seq_cst,
memory_order failure_order = memory_order_seq_cst) noexcept;
// 原子交换
int exchange(int desired, memory_order order = memory_order_seq_cst) noexcept;
// 原子获取并设置
int fetch_and(int mask, memory_order order = memory_order_seq_cst) noexcept;
int fetch_or(int mask, memory_order order = memory_order_seq_cst) noexcept;
int fetch_xor(int mask, memory_order order = memory_order_seq_cst) noexcept;
int fetch_add(int value, memory_order order = memory_order_seq_cst) noexcept;
int fetch_sub(int value, memory_order order = memory_order_seq_cst) noexcept;
};
使用
为了使用std::atomic,您需要先创建一个std::atomic对象。您可以使用std::atomic的构造函数来创建对象,或者使用std::make_sharedstd::atomic<T>来创建一个共享的std::atomic对象。
一旦您创建了一个std::atomic对象,您就可以使用它的成员函数来访问和修改共享变量。例如,以下代码使用std::atomic来实现一个简单的计数器:
#include <atomic>
std::atomic<int> counter;
int main() {
// 线程1
for (int i = 0; i < 1000000; i++) {
counter++;
}
// 线程2
for (int i = 0; i < 1000000; i++) {
counter++;
}
// 打印计数器值
std::cout << counter << std::endl;
return 0;
}
优点
std::atomic具有以下优点:
- 轻量级:std::atomic是一种轻量级的原子类型,它不会对程序的性能造成太大的影响。
- 安全:std::atomic是线程安全的,它可以保证多个线程同时访问和修改共享变量不会产生数据竞争。
- 灵活:std::atomic可以被特化为任何基本类型或用户定义类型,这使得它可以广泛地用于各种场景。
缺点
std::atomic也有一些缺点:
- 性能:std::atomic的性能不如互斥锁。
- 复杂性:std::atomic的API比较复杂,需要一些时间来学习和掌握。
结论
std::atomic是一种轻量级的原子类型,它允许多个线程同时访问和修改共享变量,而不会产生数据竞争。std::atomic具有安全、灵活等优点,但性能不如互斥锁。在选择使用std::atomic还是互斥锁时,需要权衡两者的优缺点。