我正在学习Golang中与并发相关的问题。我写了一些代码:
package main
import (
"fmt"
"time"
)
func incr(num *int) {
*num = *num + 1
}
func main() {
var a = 0
for i := 0; i < 50; i++ {
go incr(&a)
}
incr(&a)
time.Sleep(1 * time.Second)
fmt.Println(a)
}
此代码的结果是:51
在这段代码中,我声明了a
变量,并在50个正在运行的goroutine中增加了该变量。我已阅读并无法理解该代码的内容应该失败,因为多个goroutine正在写入同一内存地址。在这种情况下,我应该添加sync.Mutex
锁以解决该问题。
操场上有可用的代码:https://play.golang.org/p/Tba9pfpxaHY
您能解释一下该程序中真正发生了什么吗?
答案 0 :(得分:6)
猜猜是什么?我运行了您的应用程序,并得到了不同的输出:有时49,
有时48
,有时50
(有时51
)。
如果您在启用了竞赛检测器(go run -race play.go
)的情况下运行您的应用,则它会告诉您数据竞赛:
==================
WARNING: DATA RACE
Read at 0x00c00009a010 by goroutine 7:
main.incr()
/home/icza/gows/src/play/play.go:9 +0x3a
Previous write at 0x00c00009a010 by goroutine 6:
main.incr()
/home/icza/gows/src/play/play.go:9 +0x50
Goroutine 7 (running) created at:
main.main()
/home/icza/gows/src/play/play.go:17 +0x83
Goroutine 6 (finished) created at:
main.main()
/home/icza/gows/src/play/play.go:17 +0x83
==================
发生数据争夺时,您的应用行为为未定义。 “有时似乎工作”也符合“未定义”的行为,但是未定义也意味着它也可以做其他任何事情。
查看相关问题:
Assign a map to another map is safety in golang?
Is it safe to read a function pointer concurrently without a lock?
golang struct concurrent read and write without Lock is also running ok?