3 回答

TA貢獻1921條經驗 獲得超9個贊
你有數據競爭。結果未定義。
$ go run -race racer.go
==================
WARNING: DATA RACE
Read at 0x00c000016110 by goroutine 7:
? main.main.func1()
? ? ? /home/peter/gopath/racer.go:17 +0x7f
Previous write at 0x00c000016110 by main goroutine:
? main.main()
? ? ? /home/peter/gopath/racer.go:14 +0xf1
Goroutine 7 (running) created at:
? main.main()
? ? ? /home/peter/gopath/racer.go:16 +0xcd
==================
0 1 1
0 2 2
0 3 3
0 4 4
0 5 5
0 6 6
0 7 7
0 8 8
0 9 9
==================
WARNING: DATA RACE
Read at 0x00c000016108 by goroutine 16:
? main.main.func1()
? ? ? /home/peter/gopath/racer.go:17 +0x50
Previous write at 0x00c000016108 by main goroutine:
? main.main()
? ? ? /home/peter/gopath/racer.go:13 +0x140
Goroutine 16 (running) created at:
? main.main()
? ? ? /home/peter/gopath/racer.go:16 +0xcd
==================
1 10 11
1 1 2
1 2 3
1 3 4
1 4 5
1 5 6
1 6 7
1 7 8
1 8 9
1 9 10
2 10 12
2 1 3
2 2 4
2 3 5
2 4 6
2 5 7
2 6 8
2 7 9
2 8 10
2 9 11
3 10 13
3 1 4
3 2 5
3 3 6
3 4 7
3 5 8
3 6 9
3 7 10
3 8 11
3 9 12
4 10 14
4 1 5
4 2 6
4 3 7
4 4 8
4 5 9
4 6 10
4 7 11
4 8 12
4 9 13
5 10 15
5 1 6
5 2 7
5 3 8
5 4 9
5 5 10
5 6 11
5 7 12
5 8 13
5 9 14
6 10 16
6 1 7
6 2 8
6 3 9
6 4 10
6 5 11
6 6 12
6 7 13
6 8 14
6 9 15
7 10 17
7 1 8
7 2 9
7 3 10
7 4 11
7 5 12
7 6 13
7 7 14
7 8 15
7 9 16
8 10 18
8 1 9
8 2 10
8 3 11
8 4 12
8 5 13
8 6 14
8 7 15
8 8 16
8 9 17
9 10 19
9 1 10
9 2 11
9 3 12
9 4 13
9 5 14
9 6 15
9 7 16
9 8 17
9 9 18
Found 2 data race(s)
exit status 66
$?
racer.go:
package main
import (
? ? "fmt"
? ? "runtime"
? ? "sync"
)
func main() {
? ? runtime.GOMAXPROCS(1)
? ? mutex := new(sync.Mutex)
? ? for i := 0; i < 10; i++ {
? ? ? ? for j := 0; j < 10; j++ {
? ? ? ? ? ? mutex.Lock()
? ? ? ? ? ? go func() {
? ? ? ? ? ? ? ? fmt.Println(i, j, i+j)
? ? ? ? ? ? ? ? mutex.Unlock()
? ? ? ? ? ? }()
? ? ? ? }
? ? }
}

TA貢獻1828條經驗 獲得超3個贊
您存在數據競爭,因此結果未定義。運行它并-race
選擇查看。
當您mutex.Lock()
首先在循環體內調用時,不會阻塞。然后,您啟動一個 goroutine 來讀取i
和j
,并且主 goroutine 繼續進行內循環的下一次迭代,并遞增j
。然后再次調用lock,這將阻塞直到前一個goroutine完成。
但是您已經對j
.

TA貢獻1775條經驗 獲得超11個贊
讓我來回答為什么打印時可以得到不可能的j10 。
因為當你在循環中使用 goroutine 時,fmt.Println(i, j, i+j)race with i++/j++,你無法確定打印時到底是什么值,而如果j增加到界限,有可能打印出 10。
如果你想阻止這場比賽,你可以將i,j作為參數值傳遞,例如
runtime.GOMAXPROCS(1)
for i := 0; i < 10; i++ {
for j := 0; j < 10; j++ {
go func(a, b, c int) {
fmt.Println(a, b, c);
}(i, j, i+j)
}
}
希望這可以幫助。
- 3 回答
- 0 關注
- 172 瀏覽
添加回答
舉報