Goroutine = Golang + Coroutine

GPM模型:对Goroutine分配、负载、调度

Untitled

Untitled

G:Goroutine

type g struct {
    stack       stack      // g自己的栈
    m            *m        // 隶属于哪个M
    sched        gobuf     // 保存了g的现场,goroutine切换时通过它来恢复
    atomicstatus uint32    // G的运行状态
    goid         int64
    schedlink    guintptr  // 下一个g, g链表
    preempt      bool      //抢占标记
    lockedm      muintptr  // 锁定的M,g中断恢复指定M执行
    gopc          uintptr  // 创建该goroutine的指令地址
    startpc       uintptr  // goroutine 函数的指令地址
}

G状态

M:Machine

P:Processor

逻辑处理器,P关联了的本地可运行G的队列(也称为LRQ),最多可存放256个G。

type p struct {
    id          int32
    status      uint32     // P的状态
    link        puintptr   // 下一个P, P链表
    m           muintptr   // 拥有这个P的M
    mcache      *mcache  

    // P本地runnable状态的G队列,无锁访问
    runqhead uint32
    runqtail uint32
    runq     [256]guintptr
    
    runnext guintptr       // 一个比runq优先级更高的runnable G

    // 状态为dead的G链表,在获取G时会从这里面获取
    gFree struct {
        gList
        n int32
    }

    gcBgMarkWorker       guintptr // (atomic)
    gcw gcWork

}

P状态

GMP调度流程大致如下: