2015-05-09 24 views
1
package main 
import "fmt" 

var quit chan int 
var glo int 

func test() { 
    fmt.Println(glo) 
} 

func main() { 
    glo = 0 
    n := 10000 
    quit = make(chan int, n) 
    go test() 
    for { 
     quit <- 1 
     glo++ 
    } 
} 

當我運行上面的程序時,輸出是10000,但是當我給n分配一個更大的數字(比如1000000)時,輸出將是一個隨機數比n。Golang - 爲什麼這種競爭條件發生?

我還沒有調用runtime.GOMAXPROCS(),所以這兩個goroutines不能並行運行。當我使用go run -race來檢測競爭狀態時,沒有任何競爭狀態警告。

爲什麼這種競賽狀態會發生?

+1

爲什麼你覺得這個代碼不具備競爭條件? goroutine與for循環同時運行,並且沒有執行同步。 –

回答

2

因爲在maintest goroutines之間沒有同步,所以您不知道test中的fmt.Println調用將在什麼時間發生。

當與GOMAXPROCS = 1一起運行時,答案將基本上取決於調度程序何時決定停止執行main並切換到test。循環內的發送操作是調度程序可以切換到另一個goroutine的一個點,所以如果有足夠多的循環迭代,您會希望test有機會在某個時刻執行。每次運行都不一定會在相同的迭代中切換,從而導致結果的變化。

至於與競爭檢測器捕捉這一點,它成功地抓住了問題對我來說:

$ go run -race test.go 
================== 
WARNING: DATA RACE 
Read by goroutine 5: 
    main.test() 
     /../test.go:8 +0x6e 

Previous write by main goroutine: 
    main.main() 
     /.../test.go:18 +0xfe 

Goroutine 5 (running) created at: 
    main.main() 
     /.../test.go:15 +0x8f 
================== 
... 
+1

謝謝!但是我的賽車探測器真的無法解決問題,我不知道爲什麼。我的版本是1.4.2。 – huron

+0

我測試過的系統已安裝Go 1.3.3(amd64上的Ubuntu 15.04)。我沒有在1.4.2自己測試過它。 –

+0

看來,當發生死鎖時,比賽檢測器無法解決問題。我設法防止死鎖,並且比賽探測器成功地解決了問題。 – huron