golang使用闭包时的共享变量问题

服务器

浏览数:71

2020-6-22

在并发的使用golang闭包的时候有一个共享变量问题要注意一下,看一段代码

package main

import (
	"fmt"
	"sync"
)

func main() {
	var (
		wg    sync.WaitGroup
	)

	for i := 0; i < 5; i++ {
		wg.Add(1)
		go func() {
			fmt.Println(i)
			wg.Done()
		}()
	}
	wg.Wait()
}

输出结果

5
5
5
5
5

???什么情况,为什么不是0 ~ 4 的乱序组合?

因为主协程和子协程是有执行顺序的,也就是使用主协程在一个时间片(不太明白的话,可以看看CPU调度的相关资料,原理类似)内完全是自己的show time,当它时间片用完之后,才轮到子协程执行,而这个时候,变量“i”已经是5了。

怎么避免这个问题,有两种方式。

第一种,将“i”付给一个临时变量。

package main

import (
	"fmt"
	"sync"
)

func main() {
	var (
		wg    sync.WaitGroup
	)

	for i := 0; i < 5; i++ {
		t:=i
		wg.Add(1)
		go func() {
			fmt.Println(t)
			wg.Done()
		}()
	}
	wg.Wait()
}

第二种,传参数

package main

import (
	"fmt"
	"sync"
)

func main() {
	var (
		wg    sync.WaitGroup
	)

	for i := 0; i < 5; i++ {
		wg.Add(1)
		go func(t int) {
			fmt.Println(t)
			wg.Done()
		}(i)
	}
	wg.Wait()
}

好了,就这么简单。

留一个小问题,为什么第一段代码输出的是5而不是4呢?

更多架构、PHP、GO相关踩坑实践技巧请关注我的公众号:PHP架构师

作者:anoty