golang调度程序如何在以下代码中调度goroutine?
How does the golang scheduler sched goroutine in following code?
package main
import (
"fmt"
"time"
"runtime"
)
var quit chan int = make(chan int)
func loop(a int) {
fmt.Println(a)
for i := 0; i < 30000000000; i++ {
}
fmt.Println(a)
quit <- 0
}
func main() {
runtime.GOMAXPROCS(1)
go loop(1)
time.Sleep(time.Second)
go loop(2)
for i := 0; i < 2; i++ {
<-quit
}
}
对于调度器模型(M+P+G),我想我们只有 1 个 cpu 上下文,因为我们将 GOMAXPROCS
设置为 1,并且这里只有 1 个线程(M) .
在goroutine中,for循环没有任何IO阻塞,所以不会产生新线程,所有goroutine应该还在当前线程中工作,所以我认为2个goroutine必须一个一个走,因此,结果应该是 1 1 2 2
。但实际上,结果是1 2 1 2
。为什么?
这是你程序中相关操作的顺序。
go loop(1)
调度 goroutine loop1
time.Sleep(time.Second)
开始于 main
goroutine
fmt.Println(a)
从循环 1 调用, 打印 1
- loop1 进入忙循环并保持 CPU
- 从循环 1 进入
fmt.Println(a)
进入调度程序
main
goroutine 唤醒,完成 time.Sleep
调用
go loop(2)
调度 goroutine loop2
fmt.Println(a)
从循环 2 调用, 打印 2
- loop2进入忙循环并保持CPU
- 从循环 2 进入
fmt.Println(a)
进入调度程序
- loop1 唤醒并完成
fmt.Println(a)
,打印 1
- loop1 通过退出通道
发送 0
- loop2 完成
fmt.Println(a)
, 打印 2
- loop2 通过退出通道
发送 0
package main
import (
"fmt"
"time"
"runtime"
)
var quit chan int = make(chan int)
func loop(a int) {
fmt.Println(a)
for i := 0; i < 30000000000; i++ {
}
fmt.Println(a)
quit <- 0
}
func main() {
runtime.GOMAXPROCS(1)
go loop(1)
time.Sleep(time.Second)
go loop(2)
for i := 0; i < 2; i++ {
<-quit
}
}
对于调度器模型(M+P+G),我想我们只有 1 个 cpu 上下文,因为我们将 GOMAXPROCS
设置为 1,并且这里只有 1 个线程(M) .
在goroutine中,for循环没有任何IO阻塞,所以不会产生新线程,所有goroutine应该还在当前线程中工作,所以我认为2个goroutine必须一个一个走,因此,结果应该是 1 1 2 2
。但实际上,结果是1 2 1 2
。为什么?
这是你程序中相关操作的顺序。
go loop(1)
调度 goroutine loop1time.Sleep(time.Second)
开始于main
goroutinefmt.Println(a)
从循环 1 调用, 打印1
- loop1 进入忙循环并保持 CPU
- 从循环 1 进入
fmt.Println(a)
进入调度程序 main
goroutine 唤醒,完成time.Sleep
调用go loop(2)
调度 goroutine loop2fmt.Println(a)
从循环 2 调用, 打印2
- loop2进入忙循环并保持CPU
- 从循环 2 进入
fmt.Println(a)
进入调度程序 - loop1 唤醒并完成
fmt.Println(a)
,打印1
- loop1 通过退出通道 发送
- loop2 完成
fmt.Println(a)
, 打印2
- loop2 通过退出通道 发送
0
0