我正在阅读行动。这个例子来自第6章/ listing09.go。
// This sample program demonstrates how to create race
// conditions in our programs. We don't want to do this.
package main
import (
"fmt"
"runtime"
"sync"
)
var (
// counter is a variable incremented by all goroutines.
counter int
// wg is used to wait for the program to finish.
wg sync.WaitGroup
)
// main is the entry point for all Go programs.
func main() {
// Add a count of two, one for each goroutine.
wg.Add(2)
// Create two goroutines.
go incCounter(1)
go incCounter(2)
// Wait for the goroutines to finish.
wg.Wait()
fmt.Println("Final Counter:", counter)
}
// incCounter increments the package level counter variable.
func incCounter(id int) {
// Schedule the call to Done to tell main we are done.
defer wg.Done()
for count := 0; count < 2; count++ {
// Capture the value of Counter.
value := counter
// Yield the thread and be placed back in queue.
runtime.Gosched()
// Increment our local value of Counter.
value++
// Store the value back into Counter.
counter = value
}
}
如果你在play.golang.org中运行此代码,它将是2,与本书相同。 但我的mac打印4大部分时间,有些时间2,有时甚至3。
$ go run listing09.go
Final Counter: 2
$ go run listing09.go
Final Counter: 4
$ go run listing09.go
Final Counter: 4
$ go run listing09.go
Final Counter: 4
$ go run listing09.go
Final Counter: 4
$ go run listing09.go
Final Counter: 2
$ go run listing09.go
Final Counter: 4
$ go run listing09.go
Final Counter: 2
$ go run listing09.go
Final Counter: 3
的sysinfo 去版本go1.8.1 darwin / amd64 macOS sierra Macbook Pro
书中的解释(p140)
每个goroutine都会覆盖另一个人的工作。发生goroutine交换时会发生这种情况。每个goroutine都会创建自己的计数器变量副本,然后换出另一个goroutine。当goroutine再次执行时,计数器变量的值已更改,但goroutine不会更新其副本。相反,它继续增加它的副本并将值设置回计数器变量,替换另一个goroutine执行的工作。
根据此说明,此代码应始终打印2。
为什么我得到4和3?是因为竞争条件没有发生?
为什么去游乐场总会得到2?
更新
设置runtime.GOMAXPROCS(1)
后,它开始打印2,没有4,有些3。
我想play.golang.org配置为有一个逻辑处理器。
正确的结果4没有竞争条件。一个逻辑处理器意味着一个线程GO默认具有与物理核相同的逻辑处理器。所以, 为什么一个线程(一个逻辑处理器)导致竞争条件,而多个线程打印正确答案?
我们可以说这本书的解释是错误的,因为我们也得到了3和4吗? 怎么得到3? 4是正确的。
答案 0 :(得分:2)
根据定义,种族条件是不确定的。这意味着虽然大多数时候你可能会得到一个特定的答案,但并不总是如此。
通过在多个核心上运行racy代码,您可以大大增加可能性,从而获得更广泛的结果选择。
有关竞争条件的详情,请参阅this post或this Wikipedia article。