0

0

如何在Golang中实现无锁栈_Lock-free Stack算法

P粉602998670

P粉602998670

发布时间:2026-02-15 14:00:11

|

270人浏览过

|

来源于php中文网

原创

compareandswappointer 是 go 无锁栈唯一可靠起点,因其提供指针级 cas 原子操作,支撑安全的“检查-修改”循环;其他原子操作无法保证该语义,易致链表断裂或 nil panic。

如何在golang中实现无锁栈_lock-free stack算法

为什么 sync/atomicCompareAndSwapPointer 是唯一靠谱起点

Go 没有提供原生的无锁数据结构,sync 包里所有东西(包括 MutexRWMutex)都是基于操作系统锁的。想写真正的无锁,只能靠 sync/atomic 底层原子操作,而其中能用于指针更新的只有 CompareAndSwapPointer —— 它是构建 CAS 循环的基础,其他函数如 StorePointerLoadPointer 无法保证“检查-修改”原子性,直接用会崩。

常见错误现象:panic: runtime error: invalid memory address or nil pointer dereference,往往是因为多个 goroutine 同时修改了栈顶指针,但没用 CAS 做校验,导致链表断裂或读到中间态指针。

  • 必须用 unsafe.Pointer 转换节点指针,不能直接传 *node
  • 每次 Push / Pop 都得在一个 for 循环里重试,直到 CompareAndSwapPointer 返回 true
  • 注意:Go 1.19+ 对 unsafe.Pointer 转换加了更严的规则,不能从 slice header 或栈变量取地址再转,节点必须堆分配(即用 &node{}

如何避免 ABA 问题:用计数器还是版本号

纯指针 CAS 栈在 Go 中天然面临 ABA 问题:某个节点被弹出、回收、再分配为新节点、又被压入,此时旧的栈顶指针值“碰巧”相同,CAS 误判成功。Go 没有 std::atomic<shared_ptr></shared_ptr> 那种带引用计数的智能指针,也不能像 C/C++ 那样用双字 CAS(DCAS)。

实操中只有两个现实选择:

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

上班人导航
上班人导航

上班人必备的职场办公导航网站

下载
  • uintptr 把指针和一个单调递增的计数器打包进一个 uint64,高位存计数、低位存指针(需确保指针地址低比特对齐,通常用 unsafe.Alignof 检查),再用 CompareAndSwapUint64;这是最常用也相对安全的做法
  • 不解决 ABA,而是规避:禁止内存复用 —— 所有节点一旦 Pop 就不再回收,靠 GC 清理。适用于生命周期短、吞吐不高的场景,简单但可能吃内存
  • 不要尝试用 runtime.SetFinalizer 延迟释放节点,它无法控制时机,反而加剧 ABA 风险

Pop 返回值为空时怎么判断是栈空还是竞争失败

无锁栈的 Pop 不能靠返回 nil 判定栈空,因为可能只是当前 goroutine 在 CAS 循环中被抢占,别的 goroutine 正在修改栈顶,你读到的是临时脏值。

正确做法是把“是否真正弹出成功”作为返回值的一部分:

  • 函数签名建议为 func (s *Stack) Pop() (value interface{}, ok bool)ok == false 表示栈确实空,不是重试失败
  • 关键逻辑:只有在 CAS 成功且旧栈顶非 nil 时才返回 ok = true;如果 CAS 失败,继续循环;如果某次读到 top == nil,且下一次 CAS 仍失败(说明别人也没改它),才能确认栈空
  • 别在循环里直接 return nil, false —— 这会导致调用方误以为栈空,实际只是抢不过别人

为什么生产环境慎用自研无锁栈

Go 调度器的 G-P-M 模型、GC 的写屏障、以及 runtime 对指针的强管控,让无锁结构比在 C/C++ 里更难写对。一个典型问题是:当 goroutine 在 CAS 循环中被抢占,长时间停在中间状态,会拖慢整个 P 的调度,甚至引发 GC STW 时间变长。

除非你满足以下全部条件,否则直接用 sync.Mutex + slice 更稳:

  • 压测确认锁争用是瓶颈(pprof 显示 sync.Mutex.Lock 占 CPU >15%)
  • 栈操作极频繁(>100k ops/sec)、且单次操作逻辑极轻(无 channel、无函数调用、无接口转换)
  • 能接受内存不及时释放(节点不复用)或自己维护对象池

真实项目里,多数所谓“高并发栈”场景,其实是误判了瓶颈 —— 真正卡住的往往是后续的网络 I/O 或序列化,不是栈本身。

热门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开源协议。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

403

2024.05.21

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

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

343

2025.06.09

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

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

197

2025.06.10

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

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

866

2025.06.17

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

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

76

2026.02.13

热门下载

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

精品课程

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

共32课时 | 5.2万人学习

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号