golang子线程赋值主线程数据丢失问题记录

1.问题背景

线上出现数据一下查到一下查不到的情况,后面定位问题,发现子线程数据赋值给上级线程的时候,数据丢失了。

2.问题复现

func main() {

	for i := 0; i < 100000; i++ {
		ints := make([]int, 0)
		var wg sync.WaitGroup
		wg.Add(1)
		
		go func(wg *sync.WaitGroup) {
			
			ints = Get1(wg)
			
		}(&wg)
		wg.Wait()
		
		if len(ints) == 0 {
			fmt.Println("ces ")
		}
		
	}

}

func Get1(wg *sync.WaitGroup) []int {
	defer func() {
		wg.Done()
	}()
	ints := make([]int, 0)

	for i := 0; i < 10000; i++ {
		ints = append(ints, i)
	}
	return ints
}

上面可以复现出取值为0 的情况

 3.问题疑惑

以上复现了问题,但是我发现1w次并发的时候特别少出现数据丢失的情况,10w次就频发了,这边我认为可以这样解释,10w个协程导致gc频发,数据丢失好像很合理。但是和实际情况不一致,实际,我们没开这么多协程,应该是没有频繁gc的情况。所以我们这复现了只是其中的一种情况。

4.问题确认

后面我调整代码

func main() {

	for i := 0; i < 100000; i++ {
		ints := make([]int, 0)
		var wg sync.WaitGroup
		wg.Add(1)
		var mu sync.Mutex
		go func(wg *sync.WaitGroup) {
			mu.Lock()
			ints = Get1(wg)
			mu.Unlock()
		}(&wg)
		wg.Wait()
		mu.Lock()
		if len(ints) == 0 {
			fmt.Println("ces ")
		}
		mu.Unlock()
	}

}

func Get1(wg *sync.WaitGroup) []int {
	defer func() {
		wg.Done()
	}()
	ints := make([]int, 0)

	for i := 0; i < 10000; i++ {
		ints = append(ints, i)
	}
	return ints
}

在主子协程上面赋值取值操作进行一个加锁操作,发现问题消失了,那说明我们之前的代码是线程不安全的,但是我们理论上理解,使用waitgroup应该会等到子协程执行完毕的,理论上会执行正确的。但是多线程环境下,读取和赋值的顺序是不确定的,会产生竞态条件,因此在我们加上锁之后,执行就不会再出现数据读取异常的情况,这样也是符合我们生产的问题,归根结底还是需要对同一个共享数据操作需要加上锁,或者使用chan的方式去获取参数。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值