Go语言之美-调度之美

0 阅读2分钟

Go语言之美-调度之美

GMP调度模型是Go语言的调度模型,它是Go语言的并发模型的基础。

三个核心组件

  • G:goroutine(goroutine是Go语言调度时的最小调度单位,轻量级线程,存储了协程所需执行的栈信息,状态及指令指针)
  • M:内核线程(内核线程是操作系统的最小调度单位,是真正执行的实体)
  • P:逻辑处理器(代表了执行Go代码所需的资源和上下文)

P、M、G的三角关系

首先有个全局的运行队列,其次每个P会维护一个本地运行队列。一个M必须绑定一个P才能从P的本地队列获取一个G来执行。

三种机制

1. 任务窃取

当一个P的本地队列及全局队列都空了,为了不让与之绑定的M进入休眠而浪费CPU资源,P会随机从其他P的本地任务队列中偷走一半的G放入到自己的本地队列中来执行。

2. 线程解绑

当某个M因某个G发起一个耗时很长的同步系统调用时,这个时候执行它的M会被操作系统挂起,为了避免与之绑定的P的本地运行队列被饿死,这个时候P会解绑M,重新选择一个M或新建一个M来与之绑定。

3. 抢占式调度

当一个G在执行时,为了避免某个G执行时间过长(通常10ms)而阻塞了本地队列中的其他G的执行,调度器会向运行时间过长的线程发送一个信号,Go运行时会将当前执行的G保存当前状态并挂起,将它加入到P的本地队列的末尾,然后从P的本地队列中获取下一个G来执行。