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 执行,这样才能充分利用多核,提高并发能力。