Golang slice append 使用Synv.Mutex后仍然存在Data Race,如何可以消除Data Race?

1. 运行环境

go version go1.17.9 linux/amd64
Ubuntu 20.04

2. 问题描述?

在复现一个分布式算法时,出现Data Race的提示,存在某些消息没有被追加到slice中。然后在本地写了一个简单的程序,使用go run -race .运行后发现的确是存在Data Race。
由于是初学Goalng,对于Go语言的机制不太熟悉,我觉得大概率是因为Data Race的原因导致某些数据没有append到slice中,尽管已经使用了 Sync.mutex 加锁,不知道有没有可以解决的办法?谢谢!
这是本地模拟用的代码:

type  log  struct {

    mu sync.Mutex

    sl []int64

}

func (l *log) add(i int64) {

    l.mu.Lock()

    defer l.mu.Unlock()

    fmt.Printf("data: %d --- slice: %v  \n", i, l.sl)

    l.sl = append(l.sl, i)

}

func  main() {

    l := &log{

        sl: make([]int64, 0),

    }

    for  i := 0; i < 10; i++ {

        t := i

        go l.add(int64(t))

    }

    fmt.Println(len(l.sl))

    fmt.Println(l.sl)

}

这是使用go run -race .的运行结果:

==================
WARNING: DATA RACE
Read at 0x00c000134008 by main goroutine:
  main.main()
      /home/user/go/src/abcd/main.go:28 +0x185

Previous write at 0x00c000134008 by goroutine 14:
  main.(*log).add()
      /home/user/go/src/abcd/main.go:17 +0x211
  main.main·dwrap·2()
      /home/user/go/src/abcd/main.go:26 +0x47

Goroutine 14 (finished) created at:
  main.main()
      /home/user/go/src/abcd/main.go:26 +0xcf
==================
10
==================
WARNING: DATA RACE
Read at 0x00c0000a4048 by main goroutine:
  reflect.typedmemmove()
      /usr/local/go/src/runtime/mbarrier.go:178 +0x0
  reflect.packEface()
      /usr/local/go/src/reflect/value.go:123 +0xae
  reflect.valueInterface()
      /usr/local/go/src/reflect/value.go:1394 +0x18a
  reflect.Value.Interface()
      /usr/local/go/src/reflect/value.go:1364 +0xc9
  fmt.(*pp).printValue()
      /usr/local/go/src/fmt/print.go:722 +0xca
  fmt.(*pp).printValue()
      /usr/local/go/src/fmt/print.go:865 +0x22d8
  fmt.(*pp).printArg()
      /usr/local/go/src/fmt/print.go:712 +0xdf4
  fmt.(*pp).doPrintln()
      /usr/local/go/src/fmt/print.go:1169 +0x225
  fmt.Fprintln()
      /usr/local/go/src/fmt/print.go:264 +0x5d
  fmt.Println()
      /usr/local/go/src/fmt/print.go:274 +0x23d
  main.main()
      /home/user/go/src/abcd/main.go:29 +0x1d7

Previous write at 0x00c0000a4048 by goroutine 16:
  main.(*log).add()
      /home/user/go/src/abcd/main.go:17 +0x1eb
  main.main·dwrap·2()
      /home/user/go/src/abcd/main.go:26 +0x47

Goroutine 16 (finished) created at:
  main.main()
      /home/user/go/src/abcd/main.go:26 +0xcf
==================
[0 1 2 4 3 5 6 7 8 9]
Found 2 data race(s)
exit status 66

3. 您期望得到的结果?

4. 您实际得到的结果?

最佳答案
fmt.Println(len(l.sl))
fmt.Println(l.sl)

这两句没加锁导致的

2年前 评论
yxlee (楼主) 2年前
讨论数量: 2
fmt.Println(len(l.sl))
fmt.Println(l.sl)

这两句没加锁导致的

2年前 评论
yxlee (楼主) 2年前

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!