GMP

为什么会出现协程

  • 进程和线程
    • 资源占用高
    • CPU切换成本高
    • 多线程编程需要考虑资源互斥与通信等资源共享问题,编程复杂
  • 协程
    • co-routine,将线程划分为用户空间和内核空间,用户空间的操作单位即称为协程
    • 与线程的关系
      • 1:1
        • 一一绑定,与线程没有太大区别了
      • N:1
        • 一个线程对应多个协程的调度,缺点是不支持多核
      • N:M
        • 多对多,更好的利用多核优势,缺点依赖调度器,性能和调度器实现密切相关

go中的协程

  • 轻量级,内存占用只有4k
  • 用户态切换成本低,调度灵活

GMP的调度

  • 简介
    • G
      • 协程
    • M
      • 工作线程
    • P
      • 处理器
  • 调度
    • 1. 程序启动时,会先创建M0,每个M0也会同时创建一个g0与它一一对应,用于调度其他协程
    • 2.g0进行初始化等操作,创建main协程g1,将g1挂到当前p上的本地队列中,g0完成初始化等操作后,将控制权交还给线程M,g1和M进行绑定,开始执行g1操作
    • 3.当g1执行结束后,调度器会继续取出队列中的数据进行执行
    • 4.当本地为空时,将去全局队列取出一些G放到自己的本地队列中进行执行(min(gq/maxprocnum+1, gq/2))
    • 5.如果全局队列中也为空,则会去其他p偷取一半的g存放到自己的本地队列中进行执行
    • 6.后续如果该g中继续创建g,则优先放入自己的本地队列,如果满了则将本地队列的前一半加上当前g进行顺序打乱,然后加入全局队列等待调度
    • 7.如果此时g发生阻塞了,那将会与M进行绑定,然后P唤醒休眠M列表,然后与一个空闲的M进行绑定,如果没有M将会创建一个M与之绑定继续调度执行g