![](/img/trans.png)
[英]Unexpected behavior from launching a method call on a loop variable as a goroutine
[英]Different behavior of updating global variable in goroutine
我有一個如下的程序。 它啟動NumberOfCPUs-1
goroutine,並且在每個goroutine內部僅更新全局變量x
。 輸出為x = 0
。
func main() {
var x int
threads := runtime.GOMAXPROCS(0)-1
for i := 0; i < threads; i++ {
go func() {
for {
x++
}
}()
}
time.Sleep(time.Second)
fmt.Println("x =", x)
}
如果我稍稍更改程序,如下所示:
func main() {
var x int
threads := runtime.GOMAXPROCS(0)
for i := 0; i < threads; i++ {
go func() {
for {
x++
time.Sleep(0)
}
}()
}
time.Sleep(time.Second)
fmt.Println("x =", x)
}
x
將是一些隨機的大值。
我認為這可能與goroutine調度程序有關。 在第一種情況下,goroutine的數量少於cpu內核的數量,因此可以使用所有現有goroutine執行main
func。 由於每個goroutine內都沒有發生系統調用,I / O或通道通信,因此goroutine調度程序將無法工作。 並且由於goroutine不會被中斷,因此更新后的x
沒有機會被寫回。
在第二種情況下,goroutines的數量等於cpu核心的數量,為了讓main
func有運行的機會,我在update x
之后放置了time.Sleep(0)
。 我認為每次goroutine調度程序切換goroutine時,更新后的x
都會寫回到其原始存儲位置。
誰能證實我的想法? 有什么遺漏嗎?
謝謝。
您有多個goroutines共享同一個變量x
,但讀寫操作不同步。 您有數據競賽。 因此, x
的結果是不確定的。 使用選項-race
運行種族檢測器。 請參閱“ Go Race Detector”簡介 。
package main
import (
"fmt"
"runtime"
"time"
)
func main() {
var x int
threads := runtime.GOMAXPROCS(0) - 1
for i := 0; i < threads; i++ {
go func() {
for {
x++
}
}()
}
time.Sleep(time.Second)
fmt.Println("x =", x)
}
輸出:
$ go run -race race1.go
==================
WARNING: DATA RACE
Read at 0x00c420084010 by goroutine 7:
main.main.func1()
/home/peter/gopath/src/race1.go:15 +0x3b
Previous write at 0x00c420084010 by goroutine 6:
main.main.func1()
/home/peter/gopath/src/race1.go:15 +0x54
Goroutine 7 (running) created at:
main.main()
/home/peter/gopath/src/race1.go:13 +0xb6
Goroutine 6 (running) created at:
main.main()
/home/peter/gopath/src/race1.go:13 +0xb6
==================
x = 24717968
Found 1 data race(s)
exit status 66
package main
import (
"fmt"
"runtime"
"time"
)
func main() {
var x int
threads := runtime.GOMAXPROCS(0)
for i := 0; i < threads; i++ {
go func() {
for {
x++
time.Sleep(0)
}
}()
}
time.Sleep(time.Second)
fmt.Println("x =", x)
}
輸出:
$ go run -race race2.go
==================
WARNING: DATA RACE
Read at 0x00c4200140d0 by goroutine 7:
main.main.func1()
/home/peter/gopath/src/race2.go:15 +0x3b
Previous write at 0x00c4200140d0 by goroutine 6:
main.main.func1()
/home/peter/gopath/src/race2.go:15 +0x54
Goroutine 7 (running) created at:
main.main()
/home/peter/gopath/src/race2.go:13 +0xb3
Goroutine 6 (running) created at:
main.main()
/home/peter/gopath/src/race2.go:13 +0xb3
==================
==================
WARNING: DATA RACE
Read at 0x00c4200140d0 by goroutine 8:
main.main.func1()
/home/peter/gopath/src/race2.go:15 +0x3b
Previous write at 0x00c4200140d0 by goroutine 6:
main.main.func1()
/home/peter/gopath/src/race2.go:15 +0x54
Goroutine 8 (running) created at:
main.main()
/home/peter/gopath/src/race2.go:13 +0xb3
Goroutine 6 (running) created at:
main.main()
/home/peter/gopath/src/race2.go:13 +0xb3
==================
x = 14739962
Found 2 data race(s)
exit status 66
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.