C++11通过std::atomic提供原子操作支持,实现无锁并发,提升性能。std::atomic可用于整型、指针等类型,常用操作包括store、load、exchange、compare_exchange_weak、fetch_add/sub。内存序如memory_order_relaxed、acquire、release、seq_cst控制同步行为,合理选择可优化性能。需注意类型限制和is_lock_free检查,避免误用导致逻辑错误或性能下降。

C++11引入了对原子操作的原生支持,通过
std::atomic模板类,开发者可以在多线程环境下安全地执行无锁的共享数据访问。相比传统的互斥锁(mutex),原子操作通常性能更高,特别适用于简单的读、写、增减等场景。
std::atomic基本用法
std::atomic是一个模板类,可以包装整数类型、指针类型以及部分自定义类型(需满足特定条件)。常用的基本类型如
int、
bool、
long等都可以使用。 示例:
声明一个原子整数并进行操作:
#include#include std::atomic counter(0); void increment() { for (int i = 0; i < 1000; ++i) { counter.fetch_add(1, std::memory_order_relaxed); } }
上面代码中,多个线程调用
increment不会导致数据竞争,因为
fetch_add是原子操作。
立即学习“C++免费学习笔记(深入)”;
常用原子操作函数
std::atomic提供了多种成员函数用于不同的原子操作:
- store(value):原子地将值写入变量
- load():原子地读取变量的值
- exchange(value):设置新值,并返回旧值
- compare_exchange_weak(expected, desired):比较并交换(CAS),常用于实现无锁算法
- fetch_add(), fetch_sub():原子加减,适用于整型和指针类型
std::atomicval(0); int expected = val.load(); while (!val.compare_exchange_weak(expected, 42)) { // 如果val仍等于expected,则设为42;否则更新expected为当前值重试 } // 最终val为42
内存序(Memory Order)控制
原子操作可以指定内存顺序,控制操作周围的内存访问如何排序。常用的
std::memory_order有:
- std::memory_order_relaxed:仅保证原子性,不保证顺序,性能最好
- std::memory_order_acquire:用于读操作,确保之后的读写不会被重排到该操作之前
- std::memory_order_release:用于写操作,确保之前的读写不会被重排到该操作之后
- std::memory_order_acq_rel:同时包含acquire和release语义
- std::memory_order_seq_cst:最严格的顺序一致性,默认选项
例如,在标志位同步中使用acquire/release可避免不必要的全局同步开销:
std::atomicready(false); int data = 0; // 线程1:写数据 data = 42; ready.store(true, std::memory_order_release); // 线程2:读数据 while (!ready.load(std::memory_order_acquire)) { // 等待 } // 此时data一定可见为42
原子类型的限制与注意事项
不是所有类型都能用于
std::atomic。标准库只对整型、指针和少数平凡类型提供特化。对于自定义类型,需满足“可平凡复制”(trivially copyable)且编译器支持其原子操作。
可以通过
is_lock_free()检查原子对象是否真正无锁:
std::atomica; std::cout << "lock free: " << a.is_lock_free() << std::endl;
若返回false,说明该原子操作内部可能使用了锁,性能优势降低。
基本上就这些。合理使用
std::atomic能提升并发程序效率,但要注意内存序的选择和类型限制,避免误用导致逻辑错误。尤其在无锁编程中,CAS循环和内存模型的理解尤为关键。










