首页 > 后端开发 > C++ > 正文

c++原子操作(atomic)怎么用_c++多线程同步与无锁编程【进阶】

穿越時空
发布: 2025-12-08 14:34:02
原创
310人浏览过
原子操作(std::atomic)是C++无锁同步核心,保证读-改-写不可分割;支持load/store/exchange/CAS等操作及内存序控制,适用于计数器、栈等场景,但需规避非平凡类型、ABA问题与误用relaxed序等陷阱。

c++原子操作(atomic)怎么用_c++多线程同步与无锁编程【进阶】

原子操作(std::atomic)是 C++ 多线程中实现无锁同步的核心工具,它保证对变量的读-改-写操作不可分割,避免竞态条件,同时比互斥锁更轻量、更适合高频访问场景。

基础用法:声明与常用操作

使用 std::atomic<t></t> 替代普通变量,支持整型、指针、布尔等可平凡复制(trivially copyable)类型。常见操作包括:

  • load():原子读取,可指定内存序(如 memory_order_relaxed
  • store(val):原子写入
  • exchange(val):原子交换并返回旧值
  • compare_exchange_weak/strong(expected, desired):CAS(Compare-And-Swap),无锁编程基石
  • 对整型还支持 fetch_addfetch_suboperator++ 等复合操作

示例:

  std::atomic counter{0};
  counter.fetch_add(1, std::memory_order_relaxed); // 线程安全自增

内存序(memory_order)怎么选?

内存序控制编译器重排和 CPU 指令重排,直接影响性能与正确性。日常开发中优先按语义选,而非盲目追求最弱序:

立即学习C++免费学习笔记(深入)”;

白瓜面试
白瓜面试

白瓜面试 - AI面试助手,辅助笔试面试神器

白瓜面试 162
查看详情 白瓜面试
  • memory_order_relaxed:仅保证该操作原子,不约束前后指令顺序。适用于计数器、标记位等无需同步其他数据的场景
  • memory_order_acquire:用于读操作,保证其后所有读写不被重排到它前面。常配对 release 实现“获取-释放”同步
  • memory_order_release:用于写操作,保证其前所有读写不被重排到它后面。典型用于发布共享数据
  • memory_order_acq_rel:读-改-写操作(如 fetch_add)兼有 acquire 和 release 语义
  • memory_order_seq_cst(默认):最强一致性,全局顺序一致,最安全也最慢。不确定时先用它,再逐步优化

用 CAS 实现无锁(Lock-Free Stack)

CAS 是构建无锁数据结构的关键。下面是一个简化版的无锁单链栈(仅演示核心逻辑,省略内存回收):

  struct Node {
    int data;
    Node* next;
  };
  std::atomic head{nullptr};

  void push(int val) {
    Node* node = new Node{val, nullptr};
    node->next = head.load(std::memory_order_relaxed);
    while (!head.compare_exchange_weak(node->next, node,
                                                                 std::memory_order_release,
                                                                 std::memory_order_relaxed)) {
      // 若 head 已被其他线程修改,更新 node->next 并重试
    }
  }

注意:compare_exchange_weak 可能因 ABA 问题虚假失败,需循环重试;实际项目中还需配合 hazard pointer 或 RCU 解决内存回收问题。

常见陷阱与建议

  • 不要对非平凡类型使用 atomic:如 std::atomic<:string></:string> 不合法,只能用于 POD 类型或满足 trivially copyable 的自定义结构
  • 避免误用 relaxed 序导致逻辑错误:比如用 relaxed 写标志位,又用 relaxed 读——无法保证看到最新值,必须配对 acquire/release 或用 seq_cst
  • 原子变量不能拷贝,只能移动或赋值:声明后不可 std::atomic<int> a = b;</int>,但支持 a.store(b.load())
  • 调试困难:无锁代码出错往往偶发且难以复现,建议先用 mutex 验证逻辑,再逐步替换为原子操作
  • 不是所有场景都适合无锁:高竞争下 CAS 可能频繁失败,反而比 mutex 更耗资源。简单同步优先用 std::mutexstd::shared_mutex

基本上就这些。掌握 atomic 的关键是理解「原子性」和「内存序」两个维度,动手写几个小例子(计数器、信号量、简单队列),比死记规则更有效。

以上就是c++++原子操作(atomic)怎么用_c++多线程同步与无锁编程【进阶】的详细内容,更多请关注php中文网其它相关文章!

c++速学教程(入门到精通)
c++速学教程(入门到精通)

c++怎么学习?c++怎么入门?c++在哪学?c++怎么学才快?不用担心,这里为大家提供了c++速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载
来源:php中文网
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
最新问题
开源免费商场系统广告
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新 English
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号