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 变量,会导致另一线程看到“部分初始化”的对象。

Hotpot AI Background Remover
Hotpot AI Background Remover

Hotpot.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

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

豆包大模型
豆包大模型

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

通义千问
通义千问

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

腾讯元宝
腾讯元宝

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

文心一言
文心一言

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

讯飞写作
讯飞写作

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

即梦AI
即梦AI

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

ChatGPT
ChatGPT

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

相关专题

更多
while的用法
while的用法

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

104

2023.09.25

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

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

428

2025.06.09

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

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

201

2025.07.04

string转int
string转int

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

910

2023.08.02

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

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

596

2024.08.29

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

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

294

2025.08.29

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

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

210

2025.08.29

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

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

723

2023.08.10

Golang 测试体系与代码质量保障:工程级可靠性建设
Golang 测试体系与代码质量保障:工程级可靠性建设

Go语言测试体系与代码质量保障聚焦于构建工程级可靠性系统。本专题深入解析Go的测试工具链(如go test)、单元测试、集成测试及端到端测试实践,结合代码覆盖率分析、静态代码扫描(如go vet)和动态分析工具,建立全链路质量监控机制。通过自动化测试框架、持续集成(CI)流水线配置及代码审查规范,实现测试用例管理、缺陷追踪与质量门禁控制,确保代码健壮性与可维护性,为高可靠性工程系统提供质量保障。

48

2026.02.28

热门下载

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

精品课程

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

共18课时 | 6.4万人学习

Sass 教程
Sass 教程

共14课时 | 0.9万人学习

Pandas 教程
Pandas 教程

共15课时 | 1.1万人学习

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

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