golang 中的 len() 线程安全吗?

Tho*_*mas 8 go

我每秒都在记录地图的长度;我不在乎我是否有“确切的”值/竞争条件(一个就可以了)。我很想知道这是否会引起恐慌,以及我是否必须附上len()一些.RLock()/Unlock()

我问是因为映射中的并发读/写会导致恐慌(Go 检测到),但我不知道读取长度是否算作“读取”。我试过一个测试程序,但不能产生崩溃,但我宁愿有一个确切的答案,至少是为了它。

如果重要的话,我对数组和地图的 len 都感兴趣。谢谢!

pet*_*rSO 6

这是一个竞争条件。结果是不确定的。例如,

racer.go

package main

func main() {
    m := make(map[int]int)
    l := 0
    go func() {
        for {
            l = len(m)
        }
    }()
    for i := 0; i < 10000; i++ {
        m[i] = i
    }
}
Run Code Online (Sandbox Code Playgroud)

输出:

$ go run -race racer.go
==================
WARNING: DATA RACE
Read at 0x00c00008e000 by goroutine 5:
  main.main.func1()
      /home/peter/gopath/src/racer.go:8 +0x5f

Previous write at 0x00c00008e000 by main goroutine:
  runtime.mapassign_fast64()
      /home/peter/go/src/runtime/map_fast64.go:92 +0x0
  main.main()
      /home/peter/gopath/src/racer.go:12 +0xba

Goroutine 5 (running) created at:
  main.main()
      /home/peter/gopath/src/racer.go:6 +0x92
==================
Found 1 data race(s)
exit status 66
$
Run Code Online (Sandbox Code Playgroud)

参考:

维基百科:竞争条件

Go 博客:介绍 Go Race Detector

Go:数据竞争检测器

良性数据竞争:什么可能出错?