2015-05-09 118 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