0

0

c++如何使用atomic原子操作_c++无锁编程基础教程【原理】

冰火之心

冰火之心

发布时间:2026-02-09 14:46:02

|

945人浏览过

|

来源于php中文网

原创

std::atomic 初始化必须显式,如 std::atomic x{0};load/store 需显式指定 memory_order;fetch_add 等不防 ABA;atomic_ref 仅 C++20 支持且限 trivially copyable 类型。

c++如何使用atomic原子操作_c++无锁编程基础教程【原理】

atomic 的初始化必须显式,不能依赖默认构造

绝大多数 std::atomic 类型(如 std::atomic_intstd::atomic)**没有默认构造函数**。直接声明 std::atomic x; 会导致编译错误,常见报错是 call to implicitly-deleted default constructor

正确做法是显式初始化:

  • std::atomic x{0};(推荐,C++11 起支持)
  • std::atomic x = ATOMIC_VAR_INIT(0);(C++11 兼容写法,但 C++20 已弃用)
  • 类成员中需在构造函数初始化列表里赋初值:MyClass() : counter{0} {}

漏掉初始化不仅编译失败,还容易误以为“和普通变量一样可默认为零”——这是无锁代码里隐蔽的崩溃源头。

load/store 必须指定 memory_order,别偷懒用默认

load()store() 默认使用 std::memory_order_seq_cst(顺序一致性),性能开销最大。实际场景中,多数读写并不需要全局严格顺序。

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

常见合理选择:

  • 纯计数器累加(如引用计数):counter.fetch_add(1, std::memory_order_relaxed) —— 无同步需求,最快
  • 生产者-消费者模型中的 flag 通知:ready.store(true, std::memory_order_release) 配合 ready.load(std::memory_order_acquire) —— 保证 store 前的写操作对 load 可见
  • 需要强顺序的控制变量(如全局开关):才用 std::memory_order_seq_cst

滥用 seq_cst 会让原子操作慢 2–5 倍(尤其在 ARM/AArch64 上),而用错 order(比如该用 acquire 却用了 relaxed)会导致罕见的数据竞争,复现困难。

SciMaster
SciMaster

全球首个通用型科研AI智能体

下载

fetch_add 等复合操作不是“万能安全”,仍要防 ABA 问题

fetch_addcompare_exchange_weak 这类操作本身是原子的,但它们**不解决逻辑层面的 ABA 问题**。典型例子:一个指针被释放后又恰好分配到同一地址,compare_exchange_weak 会误判为“没变过”,导致链表操作出错。

规避方式取决于场景:

  • 整数计数器(如 refcount):ABA 不影响语义,可直接用 fetch_add
  • 指针或结构体操作:需额外版本号(如 std::atomic 拆高低 32 位为指针+counter)
  • 标准库无直接支持,得自己封装;不要试图靠 compare_exchange_strong 解决 ABA —— 它只重试,不防地址复用

很多教程只讲 “compare_exchange_weak 是原子的”,却跳过 ABA 的实际触发条件(内存池、对象复用),结果上线后偶发 crash,查一周才发现是地址被重用了。

atomic_ref 在 C++20 才可用,且仅限 trivially copyable 类型

想对已有数组元素或结构体字段做原子操作?C++20 引入了 std::atomic_ref,但它有硬性限制:

  • T 必须是 trivially_copyable(如 intfloat、POD 结构),含虚函数、非平凡构造/析构的类不行
  • 引用对象生命周期内不能被移动或销毁,否则行为未定义
  • 对齐要求严格:例如 atomic_ref 要求所引用的 int 地址满足 alignof(int),数组若用 char buf[1024] 直接 reinterpret_cast,大概率崩

实践中更稳妥的做法:把需要原子访问的字段单独拎成 std::atomic 成员,而不是事后套 atomic_ref。后者适合高性能数值计算场景(如并行 reduce 数组),但调试成本高,新手慎用。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
css中float用法
css中float用法

css中float属性允许元素脱离文档流并沿其父元素边缘排列,用于创建并排列、对齐文本图像、浮动菜单边栏和重叠元素。想了解更多float的相关内容,可以阅读本专题下面的文章。

582

2024.04.28

C++中int、float和double的区别
C++中int、float和double的区别

本专题整合了c++中int和double的区别,阅读专题下面的文章了解更多详细内容。

104

2025.10.23

golang结构体相关大全
golang结构体相关大全

本专题整合了golang结构体相关大全,想了解更多内容,请阅读专题下面的文章。

302

2025.06.09

golang结构体方法
golang结构体方法

本专题整合了golang结构体相关内容,请阅读专题下面的文章了解更多。

196

2025.07.04

string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

646

2023.08.02

int占多少字节
int占多少字节

int占4个字节,意味着一个int变量可以存储范围在-2,147,483,648到2,147,483,647之间的整数值,在某些情况下也可能是2个字节或8个字节,int是一种常用的数据类型,用于表示整数,需要根据具体情况选择合适的数据类型,以确保程序的正确性和性能。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

554

2024.08.29

c++怎么把double转成int
c++怎么把double转成int

本专题整合了 c++ double相关教程,阅读专题下面的文章了解更多详细内容。

173

2025.08.29

C++中int的含义
C++中int的含义

本专题整合了C++中int相关内容,阅读专题下面的文章了解更多详细内容。

205

2025.08.29

Golang处理数据库错误教程合集
Golang处理数据库错误教程合集

本专题整合了Golang数据库错误处理方法、技巧、管理策略相关内容,阅读专题下面的文章了解更多详细内容。

130

2026.02.06

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
C# 教程
C# 教程

共94课时 | 9万人学习

C 教程
C 教程

共75课时 | 4.6万人学习

C++教程
C++教程

共115课时 | 16.8万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

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