goroutine
以后都在 github 更新,请戳 Goroutine–概览与调度
目录
相关位置文件
- src/runtime/runtime2.go
- src/runtime/proc.go
- src/plugin/plugin_dlopen.go
概览
如果你对 MPG 在Go协程调度中代表什么并且是如何工作的 感到疑惑, 请先参考 更多资料 中的 scheduling-in-go-part1 到 scheduling-in-go-part3
根据上述文章以及 Go 源码中的注释
M
操作系统线程, ‘M’ 是 machine 的简写, 这个线程其实是被操作系统调度的, 并且操作系统仍然负责把线程调度到某个核心上运行
P
逻辑处理器, 执行 Go 代码的时候, 必须要获得的资源. M 必须拥有与之相关联的 P 才能执行 Go 代码. 但是 M 不论在是否存在与之对应的 P 的时候, 都能被阻塞住或者卡在系统调用中
G
一个 Goroutine 就是一个 协程, 但是这是 Go, 所以我们把字母 “C”(Coroutine) 替换成 “G”(Goroutine), 你可以把 Goroutine 当成应用级别的线程, 他们和系统级别的线程在很多地方都非常相似, 只是说操作系统的线程是在 CPU 核心上进行上下文切换(切入切出), 而 Goroutine 是在 M 上进行上下文切换(切入切出)
# GOSSAFUNC=main GOOS=linux GOARCH=amd64 go build -gcflags "-S" simple.go
# GOSSAFUNC=main go_dev build -gcflags "-S" num_cpu.go
# GODEBUG=schedtrace=DURATION,gctrace=1 go_dev run num_cpu.go
# GODEBUG=schedtrace=DURATION go_dev run num_cpu.go
find . -name '*.go' -exec grep -nHr 'inittask' {
} \;
bootstrap 流程的一部分会在默认的 M(M0) 上运行一个 G, 这个 G 会执行 runtime.mstart
, runtime.mstart
最终会进入 schedule
函数, schedule
函数会把 G1 调度到当前的 M(M0) 上运行, G1 会进入 runtime/proc.go
的 main
函数,