探索goroutine的销毁
go version = 1.9.3
GOARCH=“amd64” GOOS=“darwin”
本文使用delve进行调试
goroutine实际不会被销毁,而是结束后放在free goroutine里等待被再次使用
测试工程
|
|
从goroutine运行时的堆栈找下线索
|
|
runtime.goexit()
每个goroutine栈底都会有runtime.goexit(),它其实就是在创建G的时候,被设置进去的。
|
|
如果只关心已经执行完毕的goroutine是如何处置的,跟踪源码发现实质起干活的是goexit0()。
|
|
|
|
mcall()是使用go汇编语言实现的。它的参数是一个函数类型。func mcall(fn func(*g))
作用就是将当前线程的执行栈先切换到g0上。然后将当前的goroutine(即执行完的goroutine对应的G实例)当成参数传给fn,在g0的栈上继续执行fn。等于换了个SP指针,然后继续执行goexit0。
|
|
runtime.goexit0()
干了几件事:
- G的状态变为_GDead,如果是系统G则更新全局计数器。
- 重置G身上一系列的属性变量。
- 解除M和G的互相引用关系。
- 放置在本地P或全局的free goroutine队列。
- 调度,寻找下一个可运行的goroutine。
|
|