gofunc过程
go func()
创建一个 goroutine 的执行流程,具体过程如下:
-
创建 goroutine:通过
go func()
来创建一个新的 goroutine。 -
队列存储:有两个存储 G(goroutine)的队列,一个是 P 的本地队列,一个是全局 G 队列。新创建的 G 会首先保存在 P 的本地队列中,如果本地队列满了,那么 G 会存入全局队列。
-
G 的执行调度:G 需要 M(操作系统线程)来执行。每个 M 必须绑定一个 P,M 和 P 是 1:1 的关系。M 会从 P 的本地队列弹出一个可执行状态的 G 来执行。如果 P 的本地队列为空,M 会从其他 M-P 组合中偷取 G,或者从全局队列中获取 G 来执行。
-
M 调度 G 的执行:M 调度 G 的执行是一个循环机制,M 会不断地调度 G,直到所有 G 被执行。
-
系统调用的处理:当 M 执行 G 时,如果 G 发生了阻塞操作(例如发起系统调用),M 也会被阻塞。此时,如果其他 G 正在等待执行,runtime 会将这个 M 从 P 上解绑,并将 M 放入空闲线程池中,启动一个新的 M 来继续处理剩余的 G。如果有空闲的 M,则复用已有的 M 来执行 G。
-
M 系统调用结束后的恢复:当系统调用结束后,runtime 会尝试让原来的 G 和 M 重新获得一个 P 并继续执行。如果成功,M 和 G 重新进入可执行状态。如果失败,G 会被放入全局队列,等待调度。
这个过程展示了 Go 语言 runtime 中调度器如何高效地管理并调度 goroutine,最大化 CPU 资源的利用率,并避免阻塞操作影响其他 goroutine 的执行。