C++如何实现基于单线程的高性能非阻塞双端任务队列

秋宇酱_9204

秋宇酱_9204

2026-07-02

307人浏览

原创

c++oding="utf-8" ?>

不能直接用 std::deque 做非阻塞双端队列,因其操作非 lock-free,存在内存重分配、迭代器失效、malloc 全局锁及缓存不友好等问题;单线程高性能场景应选用 2 的幂容量的环形缓冲(std::array + 位掩码索引),避免动态分配与分支,确保确定性延迟。

c++如何实现基于单线程的高性能非阻塞双端任务队列

为什么不能直接用 std::deque 做非阻塞双端队列

因为 std::deque 的所有操作都不是无锁(lock-free)的,哪怕只在单线程中使用,它内部仍可能触发内存重分配、迭代器失效或异常安全路径中的锁(比如某些 libc++ 实现里 push_front 会间接调用 malloc,而 malloc 在某些环境下有轻量级全局锁)。更重要的是:非阻塞(lock-free)是并发语义,单线程下谈“非阻塞”本质是想表达「零系统调用、零分支预测失败、缓存友好、确定性延迟」——std::deque 的分段式结构导致指针跳转多,prefetch 效果差,实测在高频 push/pop 场景下比紧凑环形缓冲慢 2–3 倍。

std::array + 环形索引实现固定容量双端队列

这是单线程高性能场景最稳的选择:避免动态分配、消除分支、全路径内联。关键不是“通用”,而是“你知道容量上限”。

  • frontback 用两个 size_t 索引,不取模,改用位掩码(要求容量为 2 的幂):index & (capacity - 1)
  • 判空用 size == 0,判满用 size == capacity,不依赖 front == back(那样要浪费一个槽)
  • 所有读写都用 std::atomic<t></t>?不需要——单线程下用普通数组 + restrict 提示更高效;但若未来要扩展为无锁多生产者,才需对头尾索引做 std::atomic<size_t></size_t> + memory_order_relaxed
  • 移动语义必须显式支持:入队用 std::move(elem),出队后对原位置调用 std::destroy_at(&arr[i])(C++17 起),避免析构函数在未构造对象上调用

示例核心片段:

C++ 算法竞赛自动化测试数据生成与校验框架
C++ 算法竞赛自动化测试数据生成与校验框架

根据原题生成新题面、验证器及完整测试数据,自动套用 testlib 模板,用于用户要求生成测试数据时。

下载
template <typename t size_t n>
class RingDeque {
    static_assert((N & (N-1)) == 0, "Capacity must be power of 2");
    std::array<t n> arr_;
    size_t front_ = 0;
    size_t back_ = 0;
    size_t size_ = 0;
<p>public:
void push<em>back(T&& x) {
assert(size</em> != N);
new (&arr<em>[back</em>]) T(std::move(x));
back<em> = (back</em> + 1) & (N - 1);
++size_;
}
T pop<em>front() {
assert(size</em> != 0);
T ret(std::move(arr<em>[front</em>]));
arr<em>[front</em>].~T();
front<em> = (front</em> + 1) & (N - 1);
--size_;
return ret;
}
};</p></t></typename>

当容量不可预估时:用两级环形缓冲(segmented ring)

固定容量太死板?又不想退化成 std::deque。可行折中是「固定大小的 segment + 动态 segment 链表」,但链表跳转伤性能。更优解是:分配一大块连续内存(如 64KB),按固定大小(如 256 字节)切分成 slot,每个 slot 存一个指针 + 长度字段,用游标(cursor)管理空闲区。这样仍保持局部性,且扩容只需 mmap 一次大页(Linux)或 VirtualAlloc(Windows),不触发频繁小内存分配。

  • 避免用 std::vector<:unique_ptr>></:unique_ptr>:指针间接跳转破坏 cache line,且 unique_ptr 析构开销不可忽略
  • 真正需要动态增长时,优先考虑「预分配 + reserve」策略:启动时按业务 P99 任务量分配,运行中只允许向上 resize(用 mmap(MAP_ANONYMOUS) 扩展匿名映射),不拷贝旧数据,只更新元信息
  • 如果任务对象大小差异极大(从 8 字节到 4KB),改用 slab allocator + freelist,但此时已不属于“双端队列”原语,而是自定义内存池

别忽略任务对象本身的构造/析构成本

再快的队列,如果每次 push 都触发一次 std::string 的堆分配,或者 std::function 的 type-erasure 分配,整体延迟就由队列降级为内存分配器瓶颈。实测显示:在 L3 缓存内完成的队列操作平均 3–5 ns,而一次 small-string 以外的 std::string 构造常超 50 ns。

  • 任务对象尽量 POD 或 trivially copyable;非必要不用虚函数、RTTI、异常对象
  • std::variant<taska taskb></taska> 替代 std::function<void></void>,避免堆分配和间接调用
  • 若必须延迟执行,把捕获逻辑前置:不在入队时构造闭包,而在调度前用栈上临时对象组装参数,队列只存轻量 handle(如 uint64_t id

环形缓冲的边界检查、位运算索引、对象生命周期管理——这些细节不难,但错一处就会让“单线程高性能”变成“单线程假象”。真正卡顿往往不出现在队列本身,而出现在你认为“无关紧要”的那个 std::vector::emplace_back 里。

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

相关文章

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

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

下载

相关标签:

c++

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

相关专题

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

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

2024.03.14

2068

9

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

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

2024.03.14

939

6

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

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

2024.03.14

367

5

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

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

2024.03.14

307

5

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

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

2024.03.14

346

5

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

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

2024.03.14

560

5

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

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

2024.03.21

1389

9

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

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

2024.03.22

1177

7

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

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

2024.03.25

1305

9

热门下载

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

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Conan 2 Essentials 免费课程
Conan 2 Essentials 免费课程

共0课时 | 0人学习

CMake 与 Conan 集成实践
CMake 与 Conan 集成实践

共0课时 | 0人学习

Conan 2 高级依赖模型介绍
Conan 2 高级依赖模型介绍

共0课时 | 0人学习