跳转到主内容
极星编程网:以代码为星,赴技术山海!

c++怎么使用std::atomic进行原子操作_c++原子操作的用法与性能分析

std::atomic提供原子操作避免数据竞争,适用于整型和指针类型,通过内存序控制同步强度与性能,常用于计数器、无锁结构,需注意伪共享和CAS争用问题。 在多线程编程中,数据竞争是 常见问题 。C++11引入了 std::atomic 来提供一种类型安全且高效的原子操作机制,帮助开发者避免使用互斥锁(mutex)也能实现线程安全。它适用于对基本数据类型的读写保护,比如整型、指针等。 std::atomic的基本用法 std::atomic 模板类可以包装支持平凡拷贝的类型,最常用的是整数类型和指针类型。定义一个原子变量非常简单: 整型原子操作示例:
#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 是原子加法操作,返回旧值。也可以使用 ++counter ,它会被重载为原子递增。 立即学习 “ C++免费学习笔记(深入) ”; 指针原子操作示例:
struct Node { int data; Node* next; };
std::atomic head(nullptr);

void push_node(Node* node) {
Node* old_head = head.load();
do {
node->next = old_head;
} while (!head.compare_exchange_weak(old_head, node));
}
这里使用 compare_exchange_weak 实现无锁栈的插入操作,是一种典型的CAS(Compare-And-Swap)模式。 内存序(Memory Order)的选择 std::atomic 操作可以指定内存顺序,影响性能与同步强度。常用的有: C函数速查手册(CHM版) C函数速查手册(CHM版) 下载 std::memory_order_relaxed :仅保证原子性,不保证顺序。适合计数器等无需同步场景。 std::memory_order_acquire :用于读操作,确保之后的读写不会被重排到该操作前。 std::memory_order_release :用于写操作,确保之前的读写不会被重排到该操作后。 std::memory_order_acq_rel :同时具有acquire和release语义。 std::memory_order_seq_cst :默认选项,提供最严格的顺序一致性,但开销最大。 例如,若只关心计数,可用relaxed提升性能:
counter.fetch_add(1, std::memory_order_relaxed);
若需要同步多个变量,则应使用seq_cst或搭配acquire/release。 性能分析与适用场景 原子操作的性能远高于互斥锁,尤其在低争用场景下。由于不涉及内核态切换和上下文调度,原子指令通常在用户态完成。 性能对比关键点: 缓存行冲突 :多个原子变量若位于同一缓存行,频繁修改会导致“伪共享”(False Sharing),显著降低性能。可通过填充对齐避免。 CAS循环争用 :高并发下, compare_exchange 可能多次失败重试,退化为忙等待。此时需评估是否改用锁更高效。 平台差异 :x86架构对顺序一致性支持较好,而ARM/PowerPC等弱内存模型架构对宽松内存序更敏感,需谨慎选择内存序。 一般建议: 简单计数、状态标志用 std::atomic + relaxed。 实现无锁队列、栈等结构时,配合acquire/release控制同步。 避免在 热点 路径上频繁使用seq_cst,除非确实需要全局顺序一致。 基本上就这些。合理使用 std::atomic 能有效提升并发性能,但要注意内存序语义和硬件特性,避免误用带来隐患。

相关文章