聊聊 g0
很多时候,当我们跟着源码去理解某种事物时,基本上可以认为是以时间顺序展开,这是编年体的逻辑。还有另一种逻辑,纪传体,它以人物为中心编排史事,使得读者更聚焦于某个人物。以一种新的视角,把所有的事情串连起来,令人大呼过瘾。今天我们试着以这样一种逻辑再看 g0。
回顾一下 Go 夜读第 78 期,关于调度器源码分析的内容。我们讲过,与主线程绑定的 M 对应的 g0 的主要作用是提供一个比一般 goroutine 要大的多栈(64K)供 runtime 代码执行。
初始化的过程中,在函数 runtime·rt0_go 里会给主线程的 g0 分配栈空间:

之后,主线程会与 m0 绑定,m0 又与 g0 绑定:

之后,又与 p0 绑定:

这样,主线程的这一套 GPM 就可以转起来了。接着,就创建了 main goroutine,放入 p0 的本地待运行队列。最后,通过 schedule() 函数进入调度循环。
前面说的是程序初始化的过程中,g0 是如何诞生的。当执行到 main.main() 函数,也说是用户在 main 包下写的 main 函数里,我们随手一句:
go func() {
// 要做的事
}()
就启动了一个 goroutine 时,在 Go 编译器的作用下,最终会转化成 newproc 函数。在 newproc 函数的内部,会在 g0 栈上调用 newproc1 函数,完成后续的工作。创建完成后,会将新创建的 goroutine 放入 _p_ 的本地待运行队列。
因为新增加了一个 g,这时会尝试去唤醒一个 P 来一起执行任务。判断条件是:
if atomic.Load(&sched.npidle) != 0 && atomic.Load(&sched.nmspinning) == 0 && mainStarted {
wakep()
}
即在有空闲 P 以及没有正在“找工作的 M”的情况下,才会尝试去唤醒一个 P。我们又知道,其实 P 的数量在程序运行过程中一般不会变化,所以这里所谓的唤醒其实就是把空闲的 P 利用起来。
通过 wakep() -> startm() -> newm() -> allocm() -> malg() 这条链路创建 g0,这里 g0 的栈大小实际上为 8KB。
mp.g0 = malg(8192 * sys.StackGuardMultiplier) // sys.StackGuardMultiplier 在 linux 里为 1
g0 作为一个特殊的 goroutine,为 scheduler 执行调度循环提供了场地(栈)。对于一个线程来说,g0 总是它第一个创建的 goroutine。之后,它会不断地寻找其他普通的 goroutine 来执行,直到进程退出。
当需要执行一些任务,且不想扩栈时,就可以用到 g0 了,因为 g0 的栈比较大。g0 其他的一些“职责”有:创建 goroutine、deferproc 函数里新建 _defer、垃圾回收相关的工作(例如 stw、扫描 goroutine 的执行栈、一些标识清扫的工作、栈增长)等等。
因为 g0 这样一个特殊的 goroutine 所做的工作,使得 Go 程序运行地更快。
注:最近在 medium 上看到了一个非常赞的关于 Go 的博客,题图画得很有阅读的欲望。这篇文章也是参考于其中的一篇。
聊聊 g0的更多相关文章
- Django web 应用 http 协议 web框架
一:什么是web 应用程序 Web应用程序是一种可以通过Web访问的应用程序,程序的最大好处是用户很容易访问应用程序,用户只需要有浏览器即可,不需要再安装其他软件 应用程序有两种模式C/S.B/S. ...
- 聊聊Unity项目管理的那些事:Git-flow和Unity
0x00 前言 目前所在的团队实行敏捷开发已经有了一段时间了.敏捷开发中重要的一个话题便是如何对项目进行恰当的版本管理.项目从最初使用svn到之后的Git One Track策略再到现在的GitFlo ...
- Mono为何能跨平台?聊聊CIL(MSIL)
前言: 其实小匹夫在U3D的开发中一直对U3D的跨平台能力很好奇.到底是什么原理使得U3D可以跨平台呢?后来发现了Mono的作用,并进一步了解到了CIL的存在.所以,作为一个对Unity3D跨平台能力 ...
- fir.im Weekly - 聊聊 Google 开发者大会
中国互联网的三大错觉:索尼倒闭,诺基亚崛起,谷歌重返中国.12月8日,2016 Google 开发者大会正式发布了Google Developers 中国网站 ,包含了Android Develope ...
- 聊聊asp.net中Web Api的使用
扯淡 随着app应用的崛起,后端服务开发的也越来越多,除了很多优秀的nodejs框架之外,微软当然也会在这个方面提供更便捷的开发方式.这是微软一贯的作风,如果从开发的便捷性来说的话微软是当之无愧的老大 ...
- 没有神话,聊聊decimal的“障眼法”
0x00 前言 在上一篇文章<妥协与取舍,解构C#中的小数运算>的留言区域有很多朋友都不约而同的说道了C#中的decimal类型.事实上之前的那篇文章的立意主要在于聊聊使用二进制的计算机是 ...
- 聊聊 C 语言中的 sizeof 运算
聊聊 sizeof 运算 在这两次的课上,同学们已经学到了数组了.下面几节课,应该就会学习到指针.这个速度的确是很快的. 对于同学们来说,暂时应该也有些概念理解起来可能会比较的吃力. 先说一个概念叫内 ...
- 聊聊 Apache 开源协议
摘要 用一句话概括 Apache License 就是,你可以用这代码,但是如果开源你必须保留我写的声明:你可以改我的代码,但是如果开源你必须写清楚你改了哪些:你可以加新的协议要求,但不能与我所 公布 ...
- 【原】聊聊js代码异常监控
在平时的工作,js报错是比较常见的一个情景,尤其是有一些错误可能我们在本地测试的时候测试不出来,当发布到线上之后才可以发现,如果抢救及时,那还好,假如很晚才发 现,那就可能造成很大的损失了.如果我们前 ...
随机推荐
- 题解-Happy New Year
题解-Happy New Year Happy New Year 给定 \(n\),\(m\) 和 \(k\).有一个序列 \(a\{m\}\) 初始值为 \(0\).有 \(n\) 种操作,每种可以 ...
- STL—— 容器(vector)数据插入insert()方法 的返回值
vector 容器下的 insert() 方法拥有返回值,由于insert() 方法拥有4种重载函数,他的返回值不尽相同. 第一种,插入单个元素后的返回值: 1 #include <iostre ...
- Springboot mini - Solon详解(六)- Solon的校验框架使用、定制与扩展
Springboot min -Solon 详解系列文章: Springboot mini - Solon详解(一)- 快速入门 Springboot mini - Solon详解(二)- Solon ...
- Linux下双网卡绑定bond配置实例详解
本文源自:http://blog.itpub.net/31015730/viewspace-2150185/ 一.什么是bond? 网卡bond是通过多张网卡绑定为一个逻辑网卡,实现本地网卡冗余,带宽 ...
- collectd+infludb+grafana实现tomcat JVM监控
前提条件:已安装好java环境,tomcat,influxdb和collectd.本文暂不提供以上内容的安装步骤 系统环境:centos7 原理:开启tomcat的jmx端口,使用collectd的c ...
- Spark内核-任务调度机制
作者:十一喵先森 链接:https://juejin.im/post/5e1c414fe51d451cad4111d1 来源:掘金 著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处. ...
- MySQL高可用(一)主备同步:MySQL是如何保证主备一致的
主备同步,也叫主从复制,是MySQL提供的一种高可用的解决方案,保证主备数据一致性的解决方案. 在生产环境中,会有很多不可控因素,例如数据库服务挂了.为了保证应用的高可用,数据库也必须要是高可用的. ...
- 官方VisualStudio.gitignore配置
官方地址 https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 示例 ## Ignore Visual Stud ...
- Java日常开发的21个坑,你踩过几个?
前言 最近看了极客时间的<Java业务开发常见错误100例>,再结合平时踩的一些代码坑,写写总结,希望对大家有帮助,感谢阅读~ 1. 六类典型空指针问题 包装类型的空指针问题 级联调用的空 ...
- 通过`RestTemplate`上传文件(InputStreamResource详解)
通过RestTemplate上传文件 1.上传文件File 碰到一个需求,在代码中通过HTTP方式做一个验证的请求,请求的参数包含了文件类型.想想其实很简单,直接使用定义好的MultiValueMap ...