我正在学习Go编程语言,并且现在正在探索 atomic 包。
在这个例子中,我正在创建一些 Goroutines,它们都需要增加一个包级别的变量。避免竞争条件有几种方法,但是现在我想使用 atomic
包来解决这个问题。
当我在 Windows 电脑上运行以下代码 (go run main.go
) 时,结果并不是我期望的 (我期望最终结果为1000)。最终数字在 900 和 1000 之间。在 Go Playground 中运行代码时,该值为 1000。
以下是我使用的代码: https://play.golang.org/p/8gW-AsKGzwq
var counter int64
var wg sync.WaitGroup
func main() {
num := 1000
wg.Add(num )
for i := 0; i < num ; i++ {
go func() {
v := atomic.LoadInt64(&counter)
v++
atomic.StoreInt64(&counter, v)
// atomic.AddInt64(&counter, 1)
// fmt.Println(v)
wg.Done()
}()
}
wg.Wait()
fmt.Println("final", counter)
}
go run main.go
final 931
go run main.go
final 960
go run main.go
final 918
我本以为竞态检测器会报错,但它没有:
go run -race main.go
final 1000
它输出了正确的值(1000)。
我正在使用 go version go1.12.7 windows/amd64
(此时最新版本)
我的问题:
- 为什么竞态检测器没有报错,但我在不使用竞态检测器运行代码时看到了不同的值?
- 我认为 Load/Store 组合无法正常工作的原因是两个 atomic 调用不是作为一个整体进行原子操作。在这种情况下,我应该使用
atomic.AddInt64
方法,是这样吗?
任何帮助都将不胜感激 :)