Goroutine 执行顺序
package main
import (
"fmt"
)
func sum(s []int,c chan int){
num:=0
for _,v:=range s {
num+=v
}
c<-num
}
func main(){
s:=[]int{7,2,8,-9,4,0}
c:=make(chan int,0)
go sum(s[len(s)/2:],c)
go sum(s[:len(s)/2],c)
//y,x:=<-c,<-c
x:=<-c
y:=<-c
fmt.Println(x,y,x+y)
}
输出:
17 -5 12
值得我好奇的是,这个输出顺序是固定的,按我之前的理解来讲,我认为这个顺序应该是变化的,就是可能先输出-5,接着再输出17,也可能先输出17,再输出-5这种顺序,我反复运行好多次,结果很出乎我的意料/
下面来解释一下原因(摘自网络)
go 关键字只是一个语法糖,可以认为 go func() 只是创建了一个 待被执行任务(G),for 循环只能保证三个任务的创建顺序是 G(a) -> G(b) -> G(c),但三个任务很可能会被分配到不同的cpu core上执行(go 的运行时调度器来分配)。所以三个任务的执行顺序是不确定的。
但是比较奇妙的是,一般情况下「在同一个 goroutine 中创建的多个任务」中最后创建那个任务最可能先被执行。原因的话就要看 go 的实现细节了:简单来说,同一 goroutine 中三个任务被创建后 理论上会按顺序 被放在同一个任务队列,但实际上最后那个任务会被放在 next(下一个要被执行的任务的意思)的位置,所以优先级最高,最可能先被执行。剩下的两个任务如果 go 运行时调度器发现有空闲的 core,就会把任务偷走点,让别的 core 执行,这样才能充分利用多核,提高并发能力。