【golang/问题记录】goroutine之间数据竞争问题

说在前面

  • go版本:go1.18.4 windows/amd64

测试代码

  • 开三个goroutine,一个不断赋值,一个隔一段时间将其置空,一个判断是否为空之后进行一些操作
    type MainStruct struct {
    	Child *ChildStruct
    }
    
    type ChildStruct struct {
    	Value int
    }
    
    func TestMain() {
    	tmp := &MainStruct{
    		Child: &ChildStruct{
    			Value: 0,
    		},
    	}
    
    	// 不断赋值
    	go func() {
    		for {
    			tmp = &MainStruct{
    				Child: &ChildStruct{
    					Value: 0,
    				},
    			}
    		}
    	}()
    	// 判空后进行一些操作
    	go func() {
    		for {
    			if tmp.Child != nil {
    				tmp.Child.Value = 0
    				tmp.Child.Value++
    			}
    		}
    	}()
    	// 不断置空
    	go func() {
    		for {
    			tmp.Child = nil
    		}
    	}()
    
    	for {
    		time.Sleep(time.Second * 10)
    	}
    }
    
  • 上述代码在执行一段时间后直接panic,原因是tmp.Childnil
    panic: runtime error: invalid memory address or nil pointer dereference
    [signal 0xc0000005 code=0x1 addr=0x0 pc=0xa8a0bc]
    
    goroutine 36 [running]:
    main.TestMain.func2()
            D:/gamemanager/src/go/test.go:393 +0x1c
    created by main.TestMain
            D:/gamemanager/src/go/test.go:389 +0xf6
    exit status 2
    
  • 但是当把判空并进行操作的那个goroutine代码改一下后,就没有panic过了
    go func() {
    	for {
    		if tmp.Child != nil {
    			// tmp.Child.Value = 0
    			tmp.Child.Value++
    		}
    	}
    }()
    
  • 对于在if这个判定中访问tmp.Child会出问题,我是明确的,因为这个时候tmp.Child的值是不确定的,但是问题是为什么在去掉一行之后却没有问题。

尝试

  • 去stackoverflow上问了下,大佬们说因为data race的存在,tmp.Child的值不确定,所以探讨这个问题没有意义。附上链接
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值