0

0

c++如何使用std::atomic原子操作_c++ 无锁编程基础与并发冲突解决【方法】

尼克

尼克

发布时间:2026-01-01 12:50:54

|

173人浏览过

|

来源于php中文网

原创

std::atomic 禁止拷贝构造和赋值以保障原子性,必须用 load/store 或 fetch_add/compare_exchange 等原子操作;compare_exchange_weak 因伪失败更高效,推荐循环使用;内存序需按需选择,错用易致数据竞争;T 需 trivially copyable 且尺寸适配,否则退化为加锁。

c++如何使用std::atomic原子操作_c++ 无锁编程基础与并发冲突解决【方法】

std::atomic 为什么不能直接赋值或拷贝

因为 std::atomic 禁止了拷贝构造和拷贝赋值操作符,这是为保证原子性不被意外破坏。试图写 std::atomic<int> a = b;</int>auto c = a; 会触发编译错误use of deleted function

  • 必须用 .load() 读取当前值(可指定内存序)
  • 必须用 .store(x) 写入新值(同样支持内存序)
  • 需要“读-改-写”时,优先用 .fetch_add().compare_exchange_weak() 等原子成员函数

compare_exchange_weak 和 compare_exchange_strong 怎么选

两者都实现 CAS(Compare-and-Swap),但 compare_exchange_weak 允许伪失败(spurious failure):即使预期值匹配,也可能返回 false。这在某些平台(如 x86 上少见,ARM 上较常见)由底层指令限制导致。

  • 循环中使用时,weak 版本通常性能更好,推荐作为默认选择
  • strong 版本保证“值不匹配才失败”,适合不能容忍重试逻辑的场景(如单次尝试关键路径)
  • 务必配合 do-while 循环使用,避免漏掉失败重试
std::atomic<int> counter{0};
int expected = counter.load();
do {
    int desired = expected + 1;
} while (!counter.compare_exchange_weak(expected, desired));

内存序(memory order)不是可有可无的配置项

省略内存序参数(如只写 a.store(42))等价于 a.store(42, std::memory_order_seq_cst),即最强一致性。但多数场景不需要这么重的同步开销。

  • std::memory_order_relaxed:仅保证原子性,不约束前后内存访问顺序 —— 计数器、标志位常用
  • std::memory_order_acquire:用于读操作,确保之后的读/写不被重排到它前面
  • std::memory_order_release:用于写操作,确保之前的读/写不被重排到它后面
  • acquire-release 配对可实现线程间同步,而无需全局顺序

错用内存序不会报错,但可能引发极难复现的数据竞争 —— 比如把 relaxed 误用于需同步的 flag 变量,会导致另一线程看到“部分初始化”的对象。

PixVerse
PixVerse

PixVerse是一款强大的AI视频生成工具,可以轻松地将多种输入转化为令人惊叹的视频。

下载

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

std::atomic 对 T 的类型要求很实际

并非所有类型都能套 std::atomic。编译期会检查 T 是否为 trivially copyable,且大小不能超过平台支持的原子指令宽度(通常 ≤ 16 字节,x86-64 下一般 ≤ 8 字节)。

  • 基本类型(intlong long、指针)基本都 OK
  • 自定义结构体只有满足 std::is_trivially_copyable_v<t></t> 且不含虚函数、非平凡构造/析构时,才可能被接受
  • 即使满足条件,若尺寸过大(如 32 字节 struct),GCC/Clang 会退化为内部加锁实现 —— 此时已不是“无锁”,且性能下降明显
  • 不确定时,用 static_assert(std::atomic<t>::is_always_lock_free)</t> 显式校验

无锁编程真正的门槛不在语法,而在对共享状态变更边界的精确刻画。一个 std::atomic_flag 能安全自旋,但若把它和非原子字段混在同一缓存行里,就可能因 false sharing 拖垮性能 —— 这类问题不会报错,只会让多核跑得比单核还慢。

热门AI工具

更多
DeepSeek
DeepSeek

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

豆包大模型
豆包大模型

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

WorkBuddy
WorkBuddy

腾讯云推出的AI原生桌面智能体工作台

腾讯元宝
腾讯元宝

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

文心一言
文心一言

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

讯飞写作
讯飞写作

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

即梦AI
即梦AI

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

ChatGPT
ChatGPT

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

相关专题

更多
while的用法
while的用法

while的用法是“while 条件: 代码块”,条件是一个表达式,当条件为真时,执行代码块,然后再次判断条件是否为真,如果为真则继续执行代码块,直到条件为假为止。本专题为大家提供while相关的文章、下载、课程内容,供大家免费下载体验。

107

2023.09.25

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

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

490

2025.06.09

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

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

202

2025.07.04

string转int
string转int

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

1051

2023.08.02

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

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

615

2024.08.29

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

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

335

2025.08.29

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

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

235

2025.08.29

线程和进程的区别
线程和进程的区别

线程和进程的区别:线程是进程的一部分,用于实现并发和并行操作,而线程共享进程的资源,通信更方便快捷,切换开销较小。本专题为大家提供线程和进程区别相关的各种文章、以及下载和课程。

766

2023.08.10

TypeScript类型系统进阶与大型前端项目实践
TypeScript类型系统进阶与大型前端项目实践

本专题围绕 TypeScript 在大型前端项目中的应用展开,深入讲解类型系统设计与工程化开发方法。内容包括泛型与高级类型、类型推断机制、声明文件编写、模块化结构设计以及代码规范管理。通过真实项目案例分析,帮助开发者构建类型安全、结构清晰、易维护的前端工程体系,提高团队协作效率与代码质量。

49

2026.03.13

热门下载

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

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
进程与SOCKET
进程与SOCKET

共6课时 | 0.4万人学习

10分钟--Midjourney创作自己的漫画
10分钟--Midjourney创作自己的漫画

共1课时 | 0.1万人学习

Midjourney 关键词系列整合
Midjourney 关键词系列整合

共13课时 | 0.9万人学习

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

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