讲师中心 微信公众号
AI工具推荐 视频效率加速

c++ 线程池任务窃取 c++如何实现一个work-stealing线程池

云丽酱_4389

云丽酱_4389

发布时间:2026-03-28 20:07:33

|

306人浏览过

|

来源于php中文网

原创

work-stealing线程池不能用std::queue实现,因其仅为单端队列,无法支持线程本地后端出入栈与窃取者前端安全pop;必须使用std::deque配合细粒度锁或C++20原子操作实现无锁后端+受保护前端访问。

c++ 线程池任务窃取 c++如何实现一个work-stealing线程池

work-stealing 线程池为什么不能靠 std::queue 实现

因为 std::queue 是单端队列,只支持一端入、一端出;而 work-stealing 要求每个线程有自己的双端任务队列(deque),自己从**后端 push/pop**(避免锁),其他线程“偷”时从**前端 pop**(降低冲突概率)。用 std::queue 会导致偷任务时必须加锁或阻塞,直接废掉窃取的意义。

常见错误现象:std::queue + 全局互斥锁 → 吞吐量比单线程还低;或偷任务时发现空队列就放弃,导致负载严重不均。

  • 必须用支持无锁后端操作、且允许前端原子 pop 的结构:C++20 前普遍用 std::deque 配合 std::mutex 或自旋锁保护前端;C++20 可考虑 std::atomic_ref + 手写 ring buffer
  • 偷任务不是“随机挑一个线程”,而是按固定顺序轮询其他线程的队列(比如 (self_id + 1) % N),避免所有线程同时盯上同一个忙线程
  • 偷任务失败后要指数退避(如 sleep(1), sleep(2), sleep(4) ns),否则 CPU 空转拉满

std::deque 用法陷阱:pop_front 不是线程安全的

std::deque 本身不是线程安全容器。即使每个线程只操作自己的 deque,**偷任务时调用另一个线程的 deque 的 pop_front 仍需同步**——这不是“读操作”,它会修改内部指针和 size。

典型错误:把 std::deque<:function>>*</:function> 暴露给所有线程,让它们自由调用 other_deque->pop_front() → 数据竞争、迭代器失效、core dump。

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

C++ Code Review Master
C++ Code Review Master

组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。

下载
  • 正确做法:每个线程的 deque 必须配一个轻量级锁(std::mutex 或 std::atomic_flag 自旋锁),仅保护 pop_front 和 empty;push_back 和 pop_back 在本线程内不加锁
  • 别在锁里做耗时操作:锁住期间禁止调用用户回调函数,只做任务取出;否则偷任务的线程会长时间阻塞其他偷取者
  • 注意 std::deque::empty() 和 size() 不是原子对:先 check empty() 再 pop_front() 之间可能被本线程自己 push 进新任务,但更危险的是——它可能刚返回 false,另一线程就偷走了最后一个任务,导致 pop_front() 抛 std::out_of_range

steal() 函数怎么写才不拖慢本地执行

偷任务的逻辑如果太重,会让本线程频繁卡在跨线程访问上,反而降低整体吞吐。关键原则:**偷是例外,不是常态;快进快出,失败立即走人**。

错误模式:每次本地队列空了就遍历所有其他线程,挨个锁 deque、check empty、pop_front、解锁 → 锁开销大、缓存行失效严重、容易引发锁竞争。

  • 只在本地队列为空时尝试偷,且最多试 1–2 个目标线程(比如下一个 ID、再下一个),不扫全表
  • 用 try_lock() 而非 lock():拿不到锁立刻跳过,避免排队等待
  • 偷到任务后,**不要直接执行**,而是先 push_back 到自己队列尾部,再照常取任务 —— 这样能保持 LIFO 局部性(刚偷来的任务很可能引用刚访问过的数据)
  • 可加一个“偷任务计数器”,连续 3 次偷失败就 sleep(std::chrono::nanoseconds(16)),避免死循环 polling

C++17/20 下如何避免 new/delete 频繁分配任务对象

每个任务包装成 std::function<void></void> 并 new 出来,会带来堆分配开销和内存碎片。尤其高频小任务场景,分配成本可能超过执行本身。

常见问题:用 std::make_shared<:function>>(...)</:function> 或裸 new,结果 profiler 显示 malloc 占 CPU 15%+。

  • 优先用栈分配 + 移动语义:把任务定义为轻量值类型(如含函数指针 + 少量捕获字段的 struct),通过 std::move 传入线程池,避免 std::function 的类型擦除开销
  • 线程本地对象池:每个线程维护一个 std::vector<:aligned_storage_t alignof>></:aligned_storage_t>,预分配一批内存,用位图管理空闲块;任务执行完自动归还
  • C++20 可用 std::pmr::polymorphic_allocator 配合 std::pmr::synchronized_pool_resource,但要注意该 resource 默认不是 per-thread,需封装一层线程局部实例

真正难的不是实现 stealing,而是让偷的过程比等锁还快,且不让内存分配成为瓶颈。很多开源实现跑 synthetic benchmark 很高,一接真实业务回调就掉帧——往往卡在 std::function 构造和堆分配上。

相关文章

c++速学教程(入门到精通)
c++速学教程(入门到精通)

c++怎么学习?c++怎么入门?c++在哪学?c++怎么学才快?不用担心,这里为大家提供了c++速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

c++

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

热门AI工具

更多
豆包大模型

豆包大模型是一款由字节跳动推出的企业级大语言模型服务平台。

讯飞智作

讯飞智作是一款AI视频创作工具,AI文本配音工具,数字人课程、营销视频制作。

DeepSeek

DeepSeek是一款面向对话、写作、编程和推理场景的AI大模型工具。

SkildArt
SkildArt Hot

SkildArt是一款AI文本写作工具,一站式 AI 视觉创作平台。

Laper
Laper Hot

Laper是专为编剧、导演和制片人推出的 AI 原生剧本创作工具。

墨刀AI
墨刀AI Hot

一款AI图像与设计工具,主要用于产品经理的专属智能体,适合需要提升相关任务效率的用户。

UP简历
UP简历 Hot

一款AI办公效率工具,主要用于基于AI技术的免费在线简历制作工具,适合需要提升相关任务效率的用户。

Lovart
Lovart Hot

一款面向视觉设计创作的AI设计平台,可通过智能体和画布工作流辅助制作海报、Logo、网页、PPT及其他视觉内容。

WorkBuddy

一款AI办公效率工具,主要用于腾讯云推出的AI原生桌面智能体工作台,适合需要提升相关任务效率的用户。

相关专题

更多
resource是什么文件
resource是什么文件

Resource文件是一种特殊类型的文件,它通常用于存储应用程序或操作系统中的各种资源信息。它们在应用程序开发中起着关键作用,并在跨平台开发和国际化方面提供支持。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

320

2023.12.20

C++ 智能指针与现代内存管理
C++ 智能指针与现代内存管理

深入讲解 C++ 现代内存管理的核心工具——智能指针,涵盖 unique_ptr 独占所有权语义、shared_ptr 引用计数机制与循环引用问题、weak_ptr 弱引用的应用场景、make_unique/make_shared 工厂函数的性能优势、自定义删除器的编写、RAII 资源管理思想的实践,以及从裸指针迁移到智能指针的重构策略,帮助开发者编写安全无泄漏的现代 C++ 代码。

339

2026.04.23

堆和栈的区别
堆和栈的区别

堆和栈的区别:1、内存分配方式不同;2、大小不同;3、数据访问方式不同;4、数据的生命周期。本专题为大家提供堆和栈的区别的相关的文章、下载、课程内容,供大家免费下载体验。

5227

2023.07.18

堆和栈区别
堆和栈区别

堆(Heap)和栈(Stack)是计算机中两种常见的内存分配机制。它们在内存管理的方式、分配方式以及使用场景上有很大的区别。本文将详细介绍堆和栈的特点、区别以及各自的使用场景。php中文网给大家带来了相关的教程以及文章欢迎大家前来学习阅读。

2308

2023.08.10

堆和栈的区别
堆和栈的区别

堆和栈的区别:1、内存分配方式不同;2、大小不同;3、数据访问方式不同;4、数据的生命周期。本专题为大家提供堆和栈的区别的相关的文章、下载、课程内容,供大家免费下载体验。

5227

2023.07.18

堆和栈区别
堆和栈区别

堆(Heap)和栈(Stack)是计算机中两种常见的内存分配机制。它们在内存管理的方式、分配方式以及使用场景上有很大的区别。本文将详细介绍堆和栈的特点、区别以及各自的使用场景。php中文网给大家带来了相关的教程以及文章欢迎大家前来学习阅读。

2308

2023.08.10

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

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

3858

2023.08.10

Java 并发编程高级实践
Java 并发编程高级实践

本专题深入讲解 Java 在高并发开发中的核心技术,涵盖线程模型、Thread 与 Runnable、Lock 与 synchronized、原子类、并发容器、线程池(Executor 框架)、阻塞队列、并发工具类(CountDownLatch、Semaphore)、以及高并发系统设计中的关键策略。通过实战案例帮助学习者全面掌握构建高性能并发应用的工程能力。

543

2025.12.01

FrankenPHP集成Laravel详细教程
FrankenPHP集成Laravel详细教程

本专题提供FrankenPHP集成Laravel的详细配置指南,全面解析运行原理、开发环境搭建、Caddyfile配置、Octane工作模式、数据库连接、队列任务、定时任务和生产环境优化,解决部署过程中常见的报错与兼容性问题。

0

2026.10.08

热门下载

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

精品课程

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

共0课时 | 0人学习

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

共0课时 | 0人学习

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

共0课时 | 0人学习

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

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn