• Go协程的实现原理是基于Go运行时(runtime)和Go调度器(scheduler)的,它们共同构成了一个M:N的协程模型,也就是说,可以将M个协程映射到N个操作系统线程上,从而实现高效的并发执行。
  • Go runtime是Go语言的核心组件之一,它负责管理内存分配、垃圾回收、协程创建和销毁、协程调度、网络轮询、系统调用等功能。
  • Go调度器是Go运行时的重要子系统之一,它负责管理和调度协程的执行,它采用了一个分层的设计,主要包括三个层次的实体:G(goroutine)、P(processor)和M(machine。
  • G(goroutine)代表一个协程,它包含了协程的执行栈、寄存器状态、调度信息等元数据,它是Go调度器的最小调度单位。
  • P(processor)代表一个逻辑处理器,它维护了一个本地协程队列、一个运行中的协程、一个运行时上下文等信息,它是Go调度器的中间调度单位,负责将本地或全局的协程分配给M执行。
  • M(machine)代表一个物理线程,它与操作系统线程一一对应,它执行P分配给它的协程,并负责处理系统调用、信号处理、垃圾回收等事件,它是Go调度器的最终执行单位。
  • Go调度器的工作流程大致如下:当创建一个新的协程时,它会被放入当前P的本地队列中;当M需要执行一个协程时,它会优先从当前P的本地队列中获取一个协程,并将其绑定到P上;当M执行完一个协程时,它会解绑P和G,并将G放回本地队列或全局队列中;当P没有可用的协程时,它会从其他P的本地队列或全局队列中窃取一些协程,并放入自己的本地队列中;当M没有可用的P时,它会从空闲P列表中获取一个P,并与之绑定;当M遇到阻塞操作时,它会解绑P和G,并将G放入等待队列中,并通知网络轮询器唤醒G;当M遇到抢占操作时,它会解绑P和G,并将G放入全局队列中,并通知调度器重新调度