Golang 并发写入变量 - 为什么这段代码有效?
Golang concurrency write to variable - why this code works?
我正在学习 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 运行 goroutines 中增加它。根据我的阅读和理解,这段代码应该会失败,因为多个 goroutine 正在写入相同的内存地址。在这种情况下,我应该添加 sync.Mutex
锁来解决这个问题。
代码在 playground 中可用:https://play.golang.org/p/Tba9pfpxaHY
你能解释一下这个程序到底发生了什么吗?
你猜怎么着?我 运行 你的应用程序,我得到不同的输出:有时 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
==================
当您有数据竞争时,您的应用程序的行为是未定义。 "Seemingly working sometimes" 也符合 "undefined" 行为,但未定义也意味着它也可以做任何其他事情。
查看相关问题:
Is it safe to read a function pointer concurrently without a lock?
我正在学习 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 运行 goroutines 中增加它。根据我的阅读和理解,这段代码应该会失败,因为多个 goroutine 正在写入相同的内存地址。在这种情况下,我应该添加 sync.Mutex
锁来解决这个问题。
代码在 playground 中可用:https://play.golang.org/p/Tba9pfpxaHY
你能解释一下这个程序到底发生了什么吗?
你猜怎么着?我 运行 你的应用程序,我得到不同的输出:有时 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
==================
当您有数据竞争时,您的应用程序的行为是未定义。 "Seemingly working sometimes" 也符合 "undefined" 行为,但未定义也意味着它也可以做任何其他事情。
查看相关问题:
Is it safe to read a function pointer concurrently without a lock?