0

0

C++如何实现无锁队列?(CAS操作实战)

穿越時空

穿越時空

发布时间:2026-03-04 12:49:02

|

839人浏览过

|

来源于php中文网

原创

最稳妥是因为spsc场景无竞争,无需处理aba或复杂内存重排;用std::atomic配2的幂循环缓冲区,避开锁与cas重试,但须正确使用memory_order_acquire/release及对齐。

c++如何实现无锁队列?(cas操作实战)

为什么直接用 std::atomic 实现单生产者单消费者队列最稳妥

因为多线程下真正的无锁(lock-free)队列,核心约束是「至少一个线程总能在有限步内完成操作」,而 SPSC 场景天然满足这个前提——没有竞争,不用处理 ABA 或内存重排的复合陷阱。用 std::atomic 配合数组循环缓冲区,既避开 std::queue 的内部锁,又不用手写 CAS 循环重试逻辑。

常见错误是试图在多生产者场景硬套单指针原子操作,结果出现 store to misaligned address 或静默数据覆盖;还有人把 std::atomic<int></int> 当作普通 int 用,忘了 load()/store() 的内存序语义。

  • 只在 SPSC 场景用此方案;MPMC 必须上 std::atomic::compare_exchange_weak + 回退重试
  • 底层数组大小必须是 2 的幂,方便用位运算取模:index & (capacity - 1)
  • 读写索引都用 std::atomic<size_t></size_t>,且 load()memory_order_acquirestore()memory_order_release
  • 避免用 operator++ 原子变量——它隐式调用 fetch_add(1),但语义易混淆,显式写更安全

compare_exchange_weak 在 MPMC 队列里为什么总失败?

本质是 CAS 操作被其他线程抢走修改权,或 CPU 缓存行伪共享(false sharing)导致缓存一致性协议频繁失效。不是代码写错,而是没处理好重试边界和内存对齐。

典型现象:队列吞吐量随线程数增加不升反降,perf 看到大量 l1d.replacementmem_inst_retired.all_stores 异常高。

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

Lexica
Lexica

一个搜索 AI 生成图片的网站,可以上传图片或prompts搜索图片。

下载
  • 必须把生产者/消费者索引、头尾指针等关键原子变量各自对齐到独立 cache line(64 字节),用 alignas(64)
  • compare_exchange_weak 要放在 do-while 循环里,失败后重新 load 当前值再试,不能只试一次
  • 别用 memory_order_relaxed 处理队列元素数据——元素写入必须在索引更新前完成,要用 memory_order_release 配对
  • GCC/Clang 下注意 __atomic_compare_exchange_nstd::atomic::compare_exchange_weak 的参数顺序差异,传错会静默失败

std::atomic_thread_fence 替代部分原子操作真的能提速?

能,但只在特定模式下有效:比如消费者端确认「所有已读索引对应的数据一定已写完」,此时用 std::atomic_thread_fence(std::memory_order_acquire) 替代每个元素的 load(memory_order_acquire),可减少指令数和 cache line 压力。

风险在于 fence 是全局屏障,容易过度同步——比如在循环里每轮都插 fence,反而比带 memory order 的原子操作还慢。

  • 仅当一批数据(如 ring buffer 中连续多个 slot)共用同一内存序约束时才考虑 fence
  • fence 不能替代原子变量本身的读写,它只约束已存在原子操作的顺序,不提供原子性
  • ARM/AArch64 上 memory_order_seq_cst fence 开销显著高于 x86,跨平台需实测
  • std::atomic_signal_fence 替代编译器重排即可的场景(如 signal handler 里),别滥用 thread_fence

调试无锁队列时,AddressSanitizerdata race 但逻辑看起来没问题?

大概率是漏了对非原子成员变量的保护,或者误以为 std::atomic 能保证整个结构体原子——它只保单个变量,结构体内其他字段仍可能被并发读写。

另一个常见原因是用 std::vector 动态扩容底层缓冲区,而 resize() 过程中旧指针仍被其他线程访问,ASan 捕获到 use-after-free。

  • 禁用 ASan 的 -fsanitize=thread(TSan)比 ASan 更适合无锁代码,它专抓数据竞争时序
  • 检查所有被多线程访问的字段:哪怕只是日志计数器,也得是 std::atomic 类型
  • ring buffer 底层必须用 new uint8_t[capacity]std::unique_ptr 管理,避免 vector 迁移内存
  • assert(this_thread::get_id() == producer_thread_id) 类型的运行时校验,快速暴露误用场景

无锁队列最难的从来不是写对 CAS,而是界定清楚哪些状态必须原子、哪些可以靠 fence 推导、哪些压根不该暴露给并发上下文——稍一模糊,bug 就藏在百万次操作之后才触发。

热门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中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

930

2023.08.02

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

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

600

2024.08.29

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

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

294

2025.08.29

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

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

212

2025.08.29

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

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

723

2023.08.10

AI安装教程大全
AI安装教程大全

2026最全AI工具安装教程专题:包含各版本AI绘图、AI视频、智能办公软件的本地化部署手册。全篇零基础友好,附带最新模型下载地址、一键安装脚本及常见报错修复方案。每日更新,收藏这一篇就够了,让AI安装不再报错!

0

2026.03.04

热门下载

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

精品课程

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

共94课时 | 10.6万人学习

C 教程
C 教程

共75课时 | 5.1万人学习

C++教程
C++教程

共115课时 | 20.3万人学习

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

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