记一次面试的坑之go闭包和协程调度考察

624 阅读2分钟

题目:下面程序执行分别输出什么?有什么不同?

func fun1(){
	for i := 0; i < 50; i++ {
		go func() {
			fmt.Println(i)
		}()
	}
	time.Sleep(time.Second)
}

//输出: @默认情况下: 2 3 23 16 15 16 17 17 27 11 29 18 32 19 19 19 19 19 19 23 17 18 27 27 27 27 27 31 31 31 18 35 35 35 16 39 39 39 50 50 50 50 39 50 50 50 50 50 50 50 @设置处理器数量等于1: 50 50 50 50 50 50 50 50 50 ...

fun fun2(){
for i := 0; i < 50; i++ {
		go func() {
			j := i
			fmt.Println(j)
		}()
	}
}

//输出: @默认情况下: 10 3 19 19 19 19 35 19 39 20 ... @设置处理器数量等于1: 50 50 50 50 50 50 50 50 50 ...

fun fun3(){
for i := 0; i < 50; i++ {
		go func(j int) {
			fmt.Println(j)
		}(i)
	}
}

//输出: @默认情况下: 2 11 3 0 13 7 ... @设置处理器数量等于1: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 ...

fun fun4(){
for i := 0; i < 50; i++ {
		go func(j int) {
			fmt.Println(j)
		}(i)
	}
}

//输出: @默认情况下: 0 10 4 5 6 3 1 7 9 11 12 21 22 18 2 19 16 15 13 23 8 14 24 17 25 29 20 28 33 32 35 34 36 37 26 30 27 39 40 38 43 42 45 44 31 41 47 46 48 49 @设置处理器数量等于1: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49

总结

Go 1.5 版本之前,默认使用的是单核心执行。从 Go 1.5 版本开始,默认开启多核并发执行,这样可以充分利用多核处理器的优势。注意单核和多核情况下并行和并发执行情况下的差异。从结果可以看出goroutine是抢占式调度,不是按创建的顺序来执行。