0

0

Golang并发编程之Worker Stealing Queue_双端队列实现

P粉602998670

P粉602998670

发布时间:2026-02-14 17:18:11

|

185人浏览过

|

来源于php中文网

原创

go中用切片+sync.pool实现无锁双端队列worker stealing:本地尾部入/出(lifo),偷任务时头部截断(fifo),避免竞争;需手动清空切片、控制cap、防止stw期间栈增长。

golang并发编程之worker stealing queue_双端队列实现

Go 里怎么用双端队列实现 worker stealing

Go 标准库没有内置双端队列(deque),worker stealing 队列得自己搭。核心思路是:每个 worker 维护一个 sync.Pool 管理的本地双端队列(通常用切片模拟),任务入队优先 append 到尾部,偷任务时从头部 copy 出一部分——这样能避免和本地 worker 的尾部操作竞争。

常见错误是直接用 container/list:它不是并发安全的,且指针跳转开销大,偷任务时遍历链表效率低;更糟的是,有人把整个队列锁住再偷,彻底废掉 stealing 的意义。

  • 本地任务推入用 append(queue, task),O(1) 均摊
  • 偷任务时用 queue = queue[stealSize:] 截断头部,比 pop 更快也更安全
  • sync.Pool 复用切片底层数组,避免频繁分配——Get() 返回的切片长度为 0,但 cap 可能很大
  • 偷任务前先 len(queue) > 2*stealSize 再动手,防止偷空后本地立刻饥饿

为什么偷任务必须从队列头部取,而不是随机或尾部

因为本地 worker 总是从尾部消费(LIFO 局部性更好,缓存友好),如果偷也从尾部拿,就会和本地执行发生写冲突(两个 goroutine 同时改切片末尾)。从头部偷(FIFO)天然错开访问位置,配合 queue = queue[n:] 截断,既无锁又无竞争。

实际中有人试过用原子操作维护两个索引(head/tail),结果发现:在高并发下,原子读写反而比切片截断慢 2–3 倍,且容易因 ABA 问题导致任务丢失。

立即学习go语言免费学习笔记(深入)”;

Zeemo AI
Zeemo AI

一款专业的视频字幕制作和视频处理工具

下载
  • 本地执行:始终 task := queue[len(queue)-1]; queue = queue[:len(queue)-1]
  • steal 执行:只读取 queue[0:stealSize],然后 queue = queue[stealSize:]
  • 切片截断不触发内存拷贝,只是修改 header 中的 len/cap 字段
  • 切忌用 queue = append(queue[:0], queue[stealSize:]...) —— 这会强制 copy,完全抵消 stealing 优势

sync.Pool 复用 deque 切片时的三个坑

sync.Pool 是好东西,但复用切片时容易踩进“残留数据”“cap 泄露”“误判空队列”三个坑。最典型的现象是:worker 偷到的任务里混着上一轮的老任务,或者某次偷完发现队列长度突然变负(其实是 cap 被误当 len 用了)。

根本原因是 Go 切片 header 包含 ptr/len/cap,而 sync.Pool.Put 不清空内容,也不重置 len。下次 Get 拿回来的切片,len 是 0,但 cap 可能还是上次的 1024。

  • Put 前必须手动清空:用 queue = queue[:0],不能只赋 nil
  • Get 后别直接 len(queue) 判空——要检查是否刚从 Pool 拿来,初始 len 就是 0;应统一用 len(queue) == 0 判逻辑空
  • 避免用 make([]Task, 0, 1024) 初始化后直接 Put:这会让 Pool 里塞满高 cap 小 len 的切片,后续 Get 到的都是“虚胖”队列,浪费内存
  • 推荐初始化方式:pool.Put(make([]Task, 0)),让 Pool 自动管理 cap 增长

worker stealing 在 GC 停顿期的实际表现

很多人以为 stealing 能绕过 GC 影响,其实不能。当 STW 发生时,所有 goroutine 暂停,正在 steal 的 goroutine 卡在 len(queue)copy 上,等 GC 结束才继续。更麻烦的是:如果偷任务过程中触发了栈增长(比如切片扩容),而此时 GC 正在扫描栈,可能造成死锁或 crash。

这不是理论风险。实测中,当单个任务平均耗时超过 5ms、队列 cap > 8k 时,STW 期间发生栈增长的概率显著上升。解决方案不是禁用 stealing,而是控制队列尺寸和任务粒度。

  • 限制单个本地队列最大 cap 为 1024,超了就强制 flush 到全局队列
  • 任务函数入口加 //go:noinline,避免编译器内联后扩大栈帧
  • steal 动作本身不分配内存——所有 copy 都复用已有切片底层数组
  • 不要在 steal 路径里调用 runtime.GC() 或任何可能触发辅助 GC 的操作

真正难的不是实现 deque,而是让 stealing 在 GC、调度器抢占、栈分裂这些底层机制之间不掉链子。每处看似微小的切片操作,背后都连着运行时的神经末梢。

相关文章

编程速学教程(入门课程)
编程速学教程(入门课程)

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

下载

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

热门AI工具

更多
DeepSeek
DeepSeek

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

豆包大模型
豆包大模型

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

通义千问
通义千问

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

腾讯元宝
腾讯元宝

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

文心一言
文心一言

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

讯飞写作
讯飞写作

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

即梦AI
即梦AI

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

ChatGPT
ChatGPT

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

相关专题

更多
golang如何定义变量
golang如何定义变量

golang定义变量的方法:1、声明变量并赋予初始值“var age int =值”;2、声明变量但不赋初始值“var age int”;3、使用短变量声明“age :=值”等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

206

2024.02.23

golang有哪些数据转换方法
golang有哪些数据转换方法

golang数据转换方法:1、类型转换操作符;2、类型断言;3、字符串和数字之间的转换;4、JSON序列化和反序列化;5、使用标准库进行数据转换;6、使用第三方库进行数据转换;7、自定义数据转换函数。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

235

2024.02.23

golang常用库有哪些
golang常用库有哪些

golang常用库有:1、标准库;2、字符串处理库;3、网络库;4、加密库;5、压缩库;6、xml和json解析库;7、日期和时间库;8、数据库操作库;9、文件操作库;10、图像处理库。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

346

2024.02.23

golang和python的区别是什么
golang和python的区别是什么

golang和python的区别是:1、golang是一种编译型语言,而python是一种解释型语言;2、golang天生支持并发编程,而python对并发与并行的支持相对较弱等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

212

2024.03.05

golang是免费的吗
golang是免费的吗

golang是免费的。golang是google开发的一种静态强类型、编译型、并发型,并具有垃圾回收功能的开源编程语言,采用bsd开源协议。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

402

2024.05.21

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

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

342

2025.06.09

golang相关判断方法
golang相关判断方法

本专题整合了golang相关判断方法,想了解更详细的相关内容,请阅读下面的文章。

197

2025.06.10

golang数组使用方法
golang数组使用方法

本专题整合了golang数组用法,想了解更多的相关内容,请阅读专题下面的文章。

845

2025.06.17

pixiv网页版官网登录与阅读指南_pixiv官网直达入口与在线访问方法
pixiv网页版官网登录与阅读指南_pixiv官网直达入口与在线访问方法

本专题系统整理pixiv网页版官网入口及登录访问方式,涵盖官网登录页面直达路径、在线阅读入口及快速进入方法说明,帮助用户高效找到pixiv官方网站,实现便捷、安全的网页端浏览与账号登录体验。

23

2026.02.13

热门下载

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

精品课程

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

共32课时 | 5.1万人学习

Go语言实战之 GraphQL
Go语言实战之 GraphQL

共10课时 | 0.8万人学习

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

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