Go 调度工作机制

lingchao · · 1362 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

本文是来自 Quora 上面一个 Go 相关的问题.

下面是 Ian Lance Taylor (Go 核心开发者兼资深元老) 给出的答案:

我将给出从 Go 1.7 开始使用的调度器的概述.

调度器有三个基本结构, 称为 G, M 和 P. 一个 G 是一个 goroutine, 一个 M 是一个操作系统线程, 一个 P 是一个(逻辑)处理器.

调度器有确切的 GOMAXPROCS 数量的 P (GOMAXPROCS是一个环境变量和运行时函数, 用来设置程序中的并发度). 为了让 M 执行一个 G, 它必须获得一个P, 然后运行 G 直到停止. G 通过进行诸如 I/O 操作的系统调用, 阻塞一个 channel 操作, 调用 C 函数, 正在被预抢占(pre-emption)或其他一些小的情况来停止. 一个 G 只能在一个安全的地方被预抢占, 在当前的实现中只能在代码发生函数调用的时候发生.

当一个 G 被类似于一个 channel 操作那样阻塞时, 它将被放置在一个队列中, M 将寻找另一个可运行的 G . 如果没有可运行的 G, 则 M 将释放 P 并进入睡眠状态.

当 G 完成系统调用时, 必须重新获取 P. 如果没有 P 可用, 它将被标记为可运行, M 将进入睡眠状态.

当 channel 操作成功时, 它会唤醒另一个 goroutine, 将其标记为可运行, 并且如果有可用的 P, 则唤醒 M 来运行它.

虽然垃圾收集器大多是并发的, 但有几点要暂时停止所有的线程才能安全地转移到下一个收集阶段. 它通过标记所有正在运行的 goroutine 来预抢占. 当他们到达安全点时, G 和 M 将进入睡眠. 当垃圾收集器是唯一剩下的正在运行的 G 时, 它将移动到下一个阶段, 然后唤醒 GOMAXPROC 数量的 M, 它们将各自找到可运行的 G, 并继续下去.

runtime.Gosched 函数促使 M 将当前的 G 放在可运行的 goroutine 列表中, 并从该列表中选择一个新的 G 开始运行.

我认为这是所有要点.


有疑问加站长微信联系(非本文作者)

本文来自:lingchao.xin

感谢作者:lingchao

查看原文:Go 调度工作机制

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

1362 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传