我目前正在学习 Go 编程语言,并且正在尝试原子包。
在此示例中,我生成了许多 Goroutine,它们都需要增加包级别变量。有多种方法可以避免竞争条件,但现在我想使用该atomic
包来解决这个问题。
在我的 Windows PC ( ) 上运行以下代码时,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版本go1.12.7 windows/amd64
(目前最新版本)
我的问题:
为什么竞争检测器没有给出错误,但是在没有竞争检测器的情况下运行代码时我是否看到不同的值?
我的理论是,加载/存储组合不起作用的原因是这两个原子调用作为一个整体并不是原子的。在这种情况下我应该使用该atomic.AddInt64
方法,对吗?
任何帮助将不胜感激 :)
一只甜甜圈
相关分类