**基本概念**
g: goroutine
m: machine
p: processor
processor可以看作goroutine的调度器,本地会维护一个256个groutine栈
machine可以看作一个系统的线程资源
1个machine可以关联多个processor,processor也可以给不同的machine执行
下面时struct源码
type processor struct {
gobuf gobuf
status uint32
gp *g
ticks uint32
syscalltick uint32
sysmontick uint32
m *machine
sealed bool
next *processor
id int32
pad [sys.CacheLineSize]byte
}
type machine struct {
g0 *g // goroutine with scheduling stack
m *m // machine's own m
blocked []*g // blocked on locks
dying int32 // if set, don't allocate new gs
id int32
fastrand [2]uint32
pad [sys.CacheLineSize - 5*sys.PtrSize]byte
}
**routine基本流程**
当一个goroutine被创建时,它会被分配到一个P(处理器)上执行。每个P都有一个本地队列,用于存储等待执行的goroutine。当一个goroutine被创建时,它会被放入当前P的本地队列中。
当一个goroutine被阻塞时,它会被移出本地队列,并被放入全局队列中。全局队列是所有P共享的,用于存储等待执行的goroutine。当一个P的本地队列为空时,它会从全局队列中获取goroutine执行。
因此,当一个goroutine被阻塞时,它会被分配到全局队列。当一个P的本地队列为空时,它会从全局队列中获取goroutine执行。
**routine队列实现**
Golang的工作窃取(Stealing work)遵循的是双端队列(Deque)策略。
每个p会维护一个本地队列,当本地队列为空时,会掉别的p的本地队列从tail获取goroutine。 slice to implement deque
go中父协程与子协程的生命周期
结论:当父协程是main协程时,父协程退出,父协程下的所有子协程也会跟着退出;当父协程不是main协程时,父协程退出,父协程下的所有子协程并不会跟着退出(子协程直到自己的所有逻辑执行完或者是main协程结束才结束)