doushe7934 2017-07-23 14:47
浏览 35


I'm reading go-in-action. This example is from chapter6/listing09.go.

// This sample program demonstrates how to create race
// conditions in our programs. We don't want to do this.
package main

import (

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.

  // Create two goroutines.
  go incCounter(1)
  go incCounter(2)

  // Wait for the goroutines to finish.
  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.

      // Increment our local value of Counter.

      // Store the value back into Counter.
      counter = value

If you run this code in, it will be 2, same as the book. But my mac print 4 most of the time, some time 2, some time even 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 go version go1.8.1 darwin/amd64 macOS sierra Macbook Pro

Explanation from the book(p140)

Each goroutine overwrites the work of the other. This happens when the goroutine swap is taking place. Each goroutine makes its own copy of the counter variable and then is swapped out for the other goroutine. When the goroutine is given time to exe- cute again, the value of the counter variable has changed, but the goroutine doesn’t update its copy. Instead it continues to increment the copy it has and set the value back to the counter variable, replacing the work the other goroutine performed.

According to this explanation, this code should always print 2.

  1. Why I got 4 and 3? Is it because race condition didn't happen?

  2. Why go playground always get 2?


After I set runtime.GOMAXPROCS(1), it starts to print 2, no 4, some 3. I guess the is configured to have one logical processor.

The right result 4 without race condition. One logical processor means one thread. GO has same logical processors as the physical cores by default.So, why one thread(one logical processor) leads to race condition while multiple thread print the right answer?

Can we say the explanation from the book is wrong since we also get 3 and 4 ? How it get 3 ? 4 is correct.

  • 写回答

1条回答 默认 最新

  • duanhao4156 2017-07-23 15:34

    Race conditions are, by definition, nondeterministic. This means that while you may get a particular answer most of the time, it will not always be so.

    By running racy code on multiple cores you greatly increases the number of possibilities, hence you get a broader selection of results.

    See this post or this Wikipedia article for more information on race conditions.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?



    • ¥15 第二个问题该怎么解决啊,完全不会编写,不会做库文件,也不知道怎么写这个代码
    • ¥15 怎么使请求通过cors
    • ¥15 WDM 驱动ACPI 相关疑问
    • ¥15 prism 跨窗体共享数据绑定 wpf
    • ¥15 hdl designer突然用不了系统的moduleware组件,请问有人遇到或者怎么解决吗?
    • ¥15 0基础计算机毕设,应该从哪开始?
    • ¥60 使用DKT40脑图划分ROI区域
    • ¥15 有偿解决C51单片机液晶屏12864显示问题
    • ¥15 IDEA构建失败?怎么搞
    • ¥15 求该题的simpson,牛顿科特斯matlab代码,越快越好