根据官方文档的描述,用Go语言编写的程序在运行的时候,对协程的调度是不确定的。也就是说某一个时间里,具体哪个协程在运行是不确定的。但是下面出现了一个反例:
package main
import (
"fmt"
)
func main() {
c := make(chan string)
done := make(chan struct{})
go feed("cat", c, done)
go feed("dog", c, done)
c <- "fish"
<-done
}
func feed(name string, ch chan string, done chan struct{}) {
meat := <-ch
fmt.Println(name, "eat", meat)
done <- struct{}{}
}
运行上面这段代码输出的总是cat eat fish
。也就是说,每次都是cat
那个协程可以拿到通道中的数据。而不是cat
和dog
随机从通道中拿到数据。这个现象和官方的描述是有出入的。但是对这段代码稍作改动,每次运行的时候,出现的结果就会是随机的,且看下面这段代码:
package main
import (
"fmt"
"runtime"
)
func init() {
runtime.GOMAXPROCS(runtime.NumCPU() * 2)
}
func main() {
c := make(chan string)
done := make(chan struct{})
go feed("cat", c, done)
go feed("dog", c, done)
c <- "fish"
<-done
}
func feed(name string, ch chan string, done chan struct{}) {
meat := <-ch
fmt.Println(name, "eat", meat)
done <- struct{}{}
}
这段代码在运行的时候,基本上dog eat fish
和cat eat fish
是随机出现的。符合官方对协程调度的描述。
第二段代码中,增加了runtime.GOMAXPROCS
,设置了最大的Process的数量。换句话说,就是允许多个 Process来调度协程。这个时候,cat
和dog
两个协程就是随机从通道中获取到数据。因此,在默认协程数量为1的时候,先启动的协程似乎优先拥有时间片,但是这还需要阅读标准库中的源代码进行确认。