• 【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)
      	}
      }
      
      • 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
    • 上述代码在执行一段时间后直接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
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
    • 但是当把判空并进行操作的那个goroutine代码改一下后,就没有panic过了
      go func() {
      	for {
      		if tmp.Child != nil {
      			// tmp.Child.Value = 0
      			tmp.Child.Value++
      		}
      	}
      }()
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
    • 对于在if这个判定中访问tmp.Child会出问题,我是明确的,因为这个时候tmp.Child的值是不确定的,但是问题是为什么在去掉一行之后却没有问题。

    尝试

    • 去stackoverflow上问了下,大佬们说因为data race的存在,tmp.Child的值不确定,所以探讨这个问题没有意义。附上链接
  • 相关阅读:
    从无到有的基于QT软件的DIY桌面番茄钟(上)
    Flink SQL: JAR Statements
    一次.net code中的placeholder导致的高cpu诊断
    PPT录屏怎么录?PPT录屏,3种方法简单操作
    3线硬件SPI驱动 HX8347 TFT屏
    Windows + Msys 下编译 TensorFlow 2.14
    LeetCode - 1705 吃苹果的最大数目
    强化学习各种符号含义解释
    jar增量打包
    立可得_第5章_自动化运营与运维解决方案
  • 原文地址:https://blog.csdn.net/qq_33446100/article/details/127865705