为了提高Go程序对于CPU的利用率。Go语言的设计者,设计了GPM模型,并且实现了一个高效的协程调度器。
协程Goroutine
从操作系统层面去看,一般可以把线程分为“用户态”和“内核态”。“用户态”可以理解为编程语言实现的线程,而“内核态”可以理解为操作系统实现的线程。“用户态”线程必须和“内核态”线程绑定,才能正常执行。
GPM模型
Go的Goroutine即为“用户态”线程的Go语言实现。而管理Goroutine和“内核态”线程绑定关系的管理器,被称为“协程调度器”。“协程调度器”的模型有三个组件组成:G(协程Goroutine)、M(线程Thread)、P(处理器Processor)。
- P的数量可以通过GOMAXPROCS环境变量设置,或者通过runtime.GOMAXPROC()函数设置。
- M的最大数量可以通过runtime/debug的SetMaxThreads()函数设置,当一个M阻塞时,会去创建一个新的M。
心中有个疑问,是否可以不需要P或者M?可当前这样的设计有更多的灵活性吧。
调度器的策略
调度器的作用,就是平衡任务和操作系统资源,而且必须是高效,高效,高效。
- 偷取,一个P从其他P的本地队列偷取G
- 移交,执行G发生阻塞,则会将当前关联的P移交给其他M执行
- 抢占,每个G占用CPU资源的时间固定,其他G能够抢占CPU资源
- 全局队列,针对P使用的本地队列,发生空载或者满载的时候,多了一层缓存机制
有种类似消息队列,削峰填谷的作用
调度器生命周期
参考文献
- 《深入理解Go语言》-刘丹冰