为了账号安全,请及时绑定邮箱和手机立即绑定

【九月打卡】第14天 go的协程-协程的抢占式调度

标签:
Go

课程名称深入Go底层原理,重写Redis中间件实战


课程章节:5-7,5-8


课程讲师:Moody


课程内容:

   协程虽然可以被gopark和系统调用完成时这样的操作挂起,但是如果没有这两个操作,协程依然无法被挂起。这就需要一个机制来主动挂起协程。

    https://img2.sycdn.imooc.com/6325f69e0001f28f09590309.jpg

通过go build -gcflags -S main.go 来看,系统在进行方法调用的时候,执行了runtime.morestack方法。

morestack方法本意是用来在方法调用的时候检查栈是否有足够的空间。

go在这个经常被调用的方法里面做了钩子,系统监控到goroutine运行超过10毫秒,就认为这个是个大协程,因此就会进行标记抢占。

※ 标记抢占

  • 系统监控协程运行超过10ms

  • 将g.stackguard0 设置为0xfffffade (抢占标志)

  • 执行morestack()时判断是否已经被标记抢占

  • 如果被抢占,直接回到schedule()

    https://img1.sycdn.imooc.com/6325fa260001926c15800948.jpg

※ 基于信号抢占

如果方法并没有涉及到函数调用,那么就永远不会去检查morestack,那么也不会去检查标记位置,最后实现调度。

那么就可以实现一个基于信号的抢占。

  • 操作系统底层中有很多基于信号的通信方式

  • 线程可以注册对应信号的处理函数

  • 注册信号SIGURG 紧急信号的处理函数,该信号用的地方非常少,基本不会发生冲突

  • GC工作的时候,向目标线程发送信号,因为GC的时候很多工作都停了,适合做抢占

  • 线程收到信号的时候会触发调度

https://img2.sycdn.imooc.com/6325fc0900014f1e15970986.jpg

doSigPreempt方法会执行一个汇编方法,最终依然回调到mcall。

该流程主要是在GC里面下钩子,GC每过一段时间必然会进行垃圾回收,正是这个时刻,向线程发起调度信号,从而完成协程调度


课程收获:

这节课基本解释了协程的被动调用方式,明白了这个原理后,就知道为什么协程会比线程快很多,因为协程本身在切换的时候基本不耗费硬件的资源,完全是依赖线程本身的一些功能进行调度

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
PHP开发工程师
手记
粉丝
2
获赞与收藏
4

关注作者,订阅最新文章

阅读免费教程

  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消