前序
正确地认识 G , M , P 三者的关系,能够对协程的调度机制有更深入的理解! 本文将会完整介绍完 go 协程的调度机制,包含:
- 调度对象的主要组成
- 各对象的关系 与 分工
- gorutine 协程是如何被执行的
- 内核线程 sysmon 对 gorutine 的管理
- gorutine 协程中断挂起 与 恢复
- GOMAXPROCS 如何影响 go 的并发性能
调度器的三个基本对象:
协程(goroutine)线程(Thread)
go 关键词处理器
G-M-P三者的关系与特点:
队列队列中GOMAXPROCS
image
局部G队列与全局G队列的关系
协程任务全局队列
Gorutine从入队到执行
gorutine空队列一个点底层线程循环执行
解答问题-①
中断,挂起
原理:
sysmon
计数 schedtickschedtick非内联函数
hello world
func main(){
runtime.GOMAXPROCS(1)
go func(){
fmt.Println("hello world")
// panic("hello world") // 强制观察输出
}()
go func(){
for {
// fmt.Println("aaa") // 非内联函数,这行注释打开,将导致 hello world 的输出
}
}()
select {}
}
中断后的恢复
- 中断的时候将寄存器里的栈信息,保存到自己的 G 对象里面
- 当再次轮到自己执行时,将自己保存的栈信息复制到寄存器里面,这样就接着上次之后运
GOMAXPROCS--性能调优
GOMAXPROCS
故,我们一般将 GOMAXPROCS 的个数设置为 CPU 的核数,且需要注意的是:
- go 1.5 版本之前的 GOMAXPROCS 默认是 1
- go 1.5 版本之后的 GOMAXPROCS 默认是 Num of cpu