C++如何实现一个高性能的无锁单生产者单消费者队列

轻明吖_6785

轻明吖_6785

2026-06-19

519人浏览

原创

不能直接用std::queue做无锁队列,因为它底层非原子、无内存序控制、不支持环形缓冲区原语;真正可行的是手写环形缓冲区+原子索引+acquire/release内存序,且缓冲区大小须为2的幂。

c++如何实现一个高性能的无锁单生产者单消费者队列

为什么不能直接用 std::queue 做无锁队列

因为 std::queue 底层依赖 std::deque 或 std::vector,所有操作都带内部互斥或非原子内存访问,根本不是无锁(lock-free)的。更关键的是,它没提供原子读写索引、内存序控制、以及环形缓冲区所需的边界处理原语——这些才是无锁 SPSC 队列的骨架。

真正可行的起点是手写环形缓冲区 + 原子索引 + 显式内存序。核心就三样:std::atomic<size_t></size_t> 管理读写位置,memory_order_acquire/memory_order_release 控制可见性,以及对缓冲区大小强制 2 的幂次(方便用位运算取模)。

std::atomic 索引怎么初始化和更新才安全

两个原子变量:m_head(消费者读位置)、m_tail(生产者写位置),初始都设为 0。更新时绝不能用 fetch_add(1) 后再算下标——这会导致 ABA 问题或越界读写。

  • 每次读/写前先用 load(memory_order_acquire) 获取当前索引
  • 计算实际下标用位与:index = atomic_val & (buffer_size - 1)(前提是 buffer_size 是 2 的幂)
  • 更新后用 store(new_val, memory_order_release) 发布新位置
  • 注意:不能用 memory_order_relaxed 做 load/store,否则编译器或 CPU 可能重排指令,导致读到旧数据

如何避免伪共享(false sharing)和缓存行冲突

生产者和消费者各自只改一个索引,但若 m_head 和 m_tail 在同一缓存行(通常 64 字节),频繁修改会触发缓存一致性协议开销,性能反而比有锁还差。

C++14
C++14

C++14 对 C++11 的修正与增强版本,适合旧系统维护和较老工具链兼容。

下载

解决方案是手动填充:

struct alignas(64) spsc_queue {
    std::atomic<size_t> m_head{0};
    char pad1[64 - sizeof(std::atomic<size_t>)];
    std::atomic<size_t> m_tail{0};
    char pad2[64 - sizeof(std::atomic<size_t>)];
    T m_buffer[BUFFER_SIZE];
};</size_t></size_t></size_t></size_t>

这样保证 m_head 和 m_tail 各占独立缓存行。别信“编译器自动对齐”,也别用 alignas(128) —— 浪费空间且无收益。

push/pop 的边界检查和内存屏障怎么配对

SPSC 场景下,不需要全局同步,只需确保:生产者写入数据后,消费者才能看到;消费者读完后,生产者才能复用该槽位。靠两组 barrier 配对:

  • push 末尾用 store(m_tail, memory_order_release):让之前所有写操作对消费者可见
  • pop 开头用 load(m_head, memory_order_acquire):确保能看到生产者 release 写过的数据
  • 判断是否为空/满时,用 (m_tail.load() - m_head.load()) 计算长度(无符号减法天然支持 wraparound)
  • 切忌在 push 中用 memory_order_acq_rel —— 这是多余开销,SPSC 不需要双向同步

真正的难点不在代码长短,而在验证:你得用 std::atomic_thread_fence 或 TSAN 检查重排,还得在真实多核机器上测吞吐抖动——很多看似正确的实现,在 ARM 或 AMD CPU 上会因内存模型差异暴露问题。

C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!

相关文章

数码产品性能查询
数码产品性能查询

该软件包括了市面上所有手机CPU,手机跑分情况,电脑CPU,电脑产品信息等等,方便需要大家查阅数码产品最新情况,了解产品特性,能够进行对比选择最具性价比的商品。

下载

相关标签:

c++

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
c++和c语言的区别有哪些
c++和c语言的区别有哪些

c++和c语言的区别:1、面向对象编程(OOP)支持不同;2、新增特性不同;3、标准库不同;4、编译方式不同;5、命名空间不同等等。想了解更多c++的相关内容,可以阅读本专题下面的文章。

2024.03.14

2248

9

c++和python学习顺序推荐
c++和python学习顺序推荐

一般建议先学习C++,再学习Python,因为这样可以逐步从较为底层的编程语言向更高级的语言过渡。想了解更多python的相关内容,可以阅读本专题下面的文章。

2024.03.14

1019

6

python和c++学习性价比分析
python和c++学习性价比分析

Python易于学习,广泛应用于Web开发、数据科学和人工智能等领域,但性能较低。C语言性能高,适用于对性能要求较高的场景,如游戏开发和系统编程,但学习曲线陡峭,错误处理复杂。想了解更多python的相关内容,可以阅读本专题下面的文章。

2024.03.14

427

5

c语言和c++一样吗
c语言和c++一样吗

c语言和c++是两种不同的编程语言,虽然有相似之处,但存在显著差异。c语言专注于过程式编程和系统级开发,以简洁、高效著称。c++作为c语言的超集,引入了面向对象编程,增强了代码组织和管理能力,但学习曲线也更陡峭。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.03.14

327

5

c语言和c++先学哪个好
c语言和c++先学哪个好

初学者选择学习c语言还是c++语言,需要根据个人学习目标、背景以及编程兴趣和预期应用方向来决定。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.03.14

406

5

c语言和c++的区别和联系
c语言和c++的区别和联系

c语言和c++是计算机科学领域应用广泛的编程语言。虽然它们有着相似的基础,但它们在语言类型、语法功能和内存管理方面存在着显著差异。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.03.14

580

5

c++软件中文更改教程
c++软件中文更改教程

对于 ide,可通过打开设置,找到语言设置,选择中文,并保存更改。对于非 ide 应用程序,可查找设置或选项,选择语言设置,更改为中文,并保存更改。想了解更多c++的相关内容,可以阅读本专题下面的文章。

2024.03.21

1409

9

python和java和c++学习性价比分析
python和java和c++学习性价比分析

Python以其易学性、丰富的库和活跃的社区而著称,适合数据科学、人工智能和Web开发。Java以其跨平台性、企业级应用开发和Android应用开发而闻名。C++以其底层控制能力、高效性能和游戏开发而著称。选择哪种语言取决于个人兴趣、职业方向和特定需求。想了解更多python和java和c++的相关内容,可以阅读本专题下面的文章。

2024.03.22

1217

7

c++和c语言学习顺序推荐
c++和c语言学习顺序推荐

对于初学者,建议先学习C语言,掌握编程基础后再转入C++,便于理解面向对象编程概念。有编程经验者可直接学习C++,快速接触高级编程技术。想了解更多c++和c语言的相关内容,可以阅读本专题下面的文章。

2024.03.25

1325

9

热门下载

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

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
C++ Core Guidelines
C++ Core Guidelines

共0课时 | 0人学习

C++ Reference
C++ Reference

共0课时 | 0人学习

C++ 官方标准说明
C++ 官方标准说明

共0课时 | 0人学习