当前位置: 首页 > news >正文

Go 语言协程管理精解

1.基础

        协程切换需要操作寄存器,这些操作需要通过汇编辅助实现。另外,每一个协程都有一个协程栈,实际上协程栈也是有结构的。汇编程序和栈结构这些概念可能大部分开发者都不太了解,在介绍协程管理之间,先简要介绍。

1.1 汇编入门

学习 Go 语言协程还需要掌握汇编程序吗?其实不需要对汇编多么熟悉,只需要简单了解常用的一些汇编指令即可。 

Go 语言本身就提供了很多工具,例如,编译工具 compile 用于编译 Go 程序,我们可以使用它将上述 Go 程序编译为汇编代码。编译命令以及编译后的汇编代码如下:

//-N 禁止优化 -l 禁止内联 -S 输出汇编
go tool compile -S -N -l test.go
// addSub 函数编译后的汇编代码
"".addSub STEXT nosplit size=49 args=0x20 locals=0x00x0000 00000 (test.go:3)    MOVQ    $0, "".~r2+24(SP)0x0009 00009 (test.go:3)    MOVQ    $0, "".~r3+32(SP)0x0012 00018 (test.go:4)    MOVQ    "".a+8(SP), AX0x0017 00023 (test.go:4)    ADDQ    "".b+16(SP), AX0x001c 00028 (test.go:4)    MOVQ    AX, "".~r2+24(SP)0x0021 00033 (test.go:4)    MOVQ    "".a+8(SP), AX0x0026 00038 (test.go:4)    SUBQ    "".b+16(SP), AX0x002b 00043 (test.go:4)    MOVQ    AX, "".~r3+32(SP)0x0030 00048 (test.go:4)    RET// main 函数编译后的汇编代码
"".main STEXT size=68 args=0x0 locals=0x280x000f 00015 (test.go:7)      SUBQ    $40, SP0x0013 00019 (test.go:7)      MOVQ    BP, 32(SP)0x0018 00024 (test.go:7)      LEAQ    32(SP), BP0x001d 00029 (test.go:8)      MOVQ    $333, (SP)0x0025 00037 (test.go:8)      MOVQ    $222, 8(SP)0x002e 00046 (test.go:8)      CALL    "".addSub(SB)0x0033 00051 (test.go:9)      MOVQ    32(SP), BP0x0038 00056 (test.go:9)      ADDQ    $40, SP0x003c 00060 (test.go:9)      RET

如下所示:

协程退出

        协程的入口函数为 gofunc,执行完成时,最后一条语句是 “RET” 汇编指令,它将从协程栈弹出 8 字节数据,并存储到程序计数器 PC,随后通过 "JMP" 指令跳转。“RET” 弹出的是函数 runtime.goexit 首地址,就相当于跳转到了函数 runtime.goexit,该函数代码如下:

//函数 runtime.goexit 是汇编代码实现的,调用了函数 runtime.goexit1
void goexit1(void){mcall(goexit0)
}//系统栈执行该函数
func goexit0(gp *g){//设置协程状态,执行回收操作casgstatus(gp,_Grunning,_Gdead)//省略了清理协程相关数据的逻辑//添加到空闲队列gfput(_p_,gp)//调度schedule()
}

        需要注意的是,函数 runtime.goexit 是汇编代码实现的,底层直接调用了函数 runtime.goexit1。同样,这里是通过函数 runtime.mcall 切换到系统栈,所以函数 runtime.goexit0 是在系统栈执行的,也是它完成的协程的收尾工作,包括修改协程状态为_Gdead,清理协程相关数据,将协程回收到逻辑处理器 P 的空闲队列,执行调度程序等。

相关文章:

  • 解决 Go 语言并发问题
  • 我问GPT flutter
  • 2024年10月湖北省自学考试报名流程(5步)
  • LLM概念梳理(一):训练流程之PT、SFT和PO
  • OriginPro快速上手指南:数据可视化与分析的利器
  • Android笔试面试题AI答之Kotlin(18)
  • 本科生毕业答辩全攻略:从开题到终期答辩的全面指南
  • 中国第一起名大师的老师颜廷利: 名字中的姓氏家谱字辈的最新解析
  • Vitis AI 进阶认知(Torch量化基础+映射+量化参数+对称性+每通道+PTQ+QAT+敏感性)
  • PHP进阶篇(奇怪的知识又增加了)
  • 局部整体(三)利用python绘制饼图
  • PostgreSQL-04-入门篇-连接多张表
  • 【微服务】Nacos配置中心和客户端数据同步模式
  • Vue3项目开发——新闻发布管理系统(一)
  • 《黑神话:悟空》总销量已破 450 万份,总销售额超过15亿元,对于单机游戏来说,这一成绩意味着什么?
  • 分享一款快速APP功能测试工具
  • CSS3 聊天气泡框以及 inherit、currentColor 关键字
  • Java的Interrupt与线程中断
  • JS笔记四:作用域、变量(函数)提升
  • Kibana配置logstash,报表一体化
  • LeetCode541. Reverse String II -- 按步长反转字符串
  • Netty 4.1 源代码学习:线程模型
  • pdf文件如何在线转换为jpg图片
  • RxJS 实现摩斯密码(Morse) 【内附脑图】
  • Shell编程
  • Vue源码解析(二)Vue的双向绑定讲解及实现
  • 分布式事物理论与实践
  • 和 || 运算
  • 什么软件可以剪辑音乐?
  • 说说动画卡顿的解决方案
  • 它承受着该等级不该有的简单, leetcode 564 寻找最近的回文数
  • 问:在指定的JSON数据中(最外层是数组)根据指定条件拿到匹配到的结果
  • 问题之ssh中Host key verification failed的解决
  • Oracle Portal 11g Diagnostics using Remote Diagnostic Agent (RDA) [ID 1059805.
  • python最赚钱的4个方向,你最心动的是哪个?
  • ​​​【收录 Hello 算法】9.4 小结
  • ​十个常见的 Python 脚本 (详细介绍 + 代码举例)
  • # 20155222 2016-2017-2 《Java程序设计》第5周学习总结
  • (175)FPGA门控时钟技术
  • (cljs/run-at (JSVM. :browser) 搭建刚好可用的开发环境!)
  • (PWM呼吸灯)合泰开发板HT66F2390-----点灯大师
  • (分布式缓存)Redis分片集群
  • (回溯) LeetCode 131. 分割回文串
  • (六)库存超卖案例实战——使用mysql分布式锁解决“超卖”问题
  • (转)Groupon前传:从10个月的失败作品修改,1个月找到成功
  • (转载)虚幻引擎3--【UnrealScript教程】章节一:20.location和rotation
  • .bat批处理出现中文乱码的情况
  • .gitignore文件—git忽略文件
  • .gitignore文件使用
  • .L0CK3D来袭:如何保护您的数据免受致命攻击
  • .NET CLR Hosting 简介
  • .NET Core 网络数据采集 -- 使用AngleSharp做html解析
  • .Net Web窗口页属性
  • .NET 项目中发送电子邮件异步处理和错误机制的解决方案
  • .Net下C#针对Excel开发控件汇总(ClosedXML,EPPlus,NPOI)