doushe7934 2017-07-23 14:47
浏览 35
已采纳

为什么goroutine的比赛条件会在一段时间后消失?

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 (
  "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
  }
}

If you run this code in play.golang.org, 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?


update:

After I set runtime.GOMAXPROCS(1), it starts to print 2, no 4, some 3. I guess the play.golang.org 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 请问如何在openpcdet上对KITTI数据集的测试集进行结果评估?
  • ¥15 powerbuilder中的datawindow数据整合到新的DataWindow
  • ¥20 有人知道这种图怎么画吗?
  • ¥15 pyqt6如何引用qrc文件加载里面的的资源
  • ¥15 安卓JNI项目使用lua上的问题
  • ¥20 RL+GNN解决人员排班问题时梯度消失
  • ¥60 要数控稳压电源测试数据
  • ¥15 能帮我写下这个编程吗
  • ¥15 ikuai客户端l2tp协议链接报终止15信号和无法将p.p.p6转换为我的l2tp线路
  • ¥15 phython读取excel表格报错 ^7个 SyntaxError: invalid syntax 语句报错