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.

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

报告相同问题?

悬赏问题

  • ¥40 复杂的限制性的商函数处理
  • ¥15 程序不包含适用于入口点的静态Main方法
  • ¥15 素材场景中光线烘焙后灯光失效
  • ¥15 请教一下各位,为什么我这个没有实现模拟点击
  • ¥15 执行 virtuoso 命令后,界面没有,cadence 启动不起来
  • ¥50 comfyui下连接animatediff节点生成视频质量非常差的原因
  • ¥20 有关区间dp的问题求解
  • ¥15 多电路系统共用电源的串扰问题
  • ¥15 slam rangenet++配置
  • ¥15 有没有研究水声通信方面的帮我改俩matlab代码