普通网友 2018-08-04 06:59
浏览 3
已采纳

比赛条件改变

《Go in action》's sample about race conditions:

var (
    counter int
    wg sync.WaitGroup
)

func main() {
    wg.Add(2)
    go incCounter(1)
    go incCounter(2)

    wg.Wait()
    fmt.Println("Final Counter:", counter)
}

func incCounter(id int) {
    defer wg.Done()

    for count := 0; count < 2; count++ {
        value := counter
        //1 fmt.Println("value=",value)
        runtime.Gosched()

        value++

        counter = value
        //2 fmt.Println("counter=",counter)
    }
}

it is said Final Counter should be 2 in the end,here is explain: "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 execute 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."

I guess it's environment reason,my machine output 4 with go 1.10.3+win10. I want to know what the go changed since the book released? And if I uncomment mark 1 Final Counter prints 2 or random if I uncomment mark 2. why?

  • 写回答

1条回答 默认 最新

  • duanpa1980 2018-08-04 07:18
    关注

    The book is wrong. The essential point about a data race is the result is undefined.

    For example, Final Counter could be any value.

    package main
    
    import (
        "fmt"
        "runtime"
        "sync"
    )
    
    var (
        counter int
        wg      sync.WaitGroup
    )
    
    func main() {
        wg.Add(2)
        go incCounter(1)
        go incCounter(2)
    
        wg.Wait()
        fmt.Println("Final Counter:", counter)
    }
    
    func incCounter(id int) {
        defer wg.Done()
    
        for count := 0; count < 2; count++ {
            value := counter
            //1 fmt.Println("value=",value)
            runtime.Gosched()
    
            value++
    
            counter = value
            //2 fmt.Println("counter=",counter)
        }
    }
    

    Output:

    $ go version
    go version devel +65fa2b615b Fri Aug 3 23:35:53 2018 +0000 linux/amd64
    $ go run racer.go
    Final Counter: 4
    $ go run racer.go
    Final Counter: 2
    $ go run racer.go
    Final Counter: 2
    $ go run racer.go
    Final Counter: 2
    $ go run racer.go
    Final Counter: 2
    $ go run racer.go
    Final Counter: 4
    $ go run racer.go
    Final Counter: 2
    $ go run racer.go
    Final Counter: 4
    $ go run -race racer.go
    ==================
    WARNING: DATA RACE
    Read at 0x0000005e4600 by goroutine 7:
      main.incCounter()
          /home/peter/gopath/src/racer.go:27 +0x6f
    
    Previous write at 0x0000005e4600 by goroutine 6:
      main.incCounter()
          /home/peter/gopath/src/racer.go:33 +0x90
    
    Goroutine 7 (running) created at:
      main.main()
          /home/peter/gopath/src/racer.go:17 +0x89
    
    Goroutine 6 (finished) created at:
      main.main()
          /home/peter/gopath/src/racer.go:16 +0x68
    ==================
    Final Counter: 4
    Found 1 data race(s)
    exit status 66
    $
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥20 怎么用dlib库的算法识别小麦病虫害
  • ¥15 华为ensp模拟器中S5700交换机在配置过程中老是反复重启
  • ¥15 java写代码遇到问题,求帮助
  • ¥15 uniapp uview http 如何实现统一的请求异常信息提示?
  • ¥15 有了解d3和topogram.js库的吗?有偿请教
  • ¥100 任意维数的K均值聚类
  • ¥15 stamps做sbas-insar,时序沉降图怎么画
  • ¥15 买了个传感器,根据商家发的代码和步骤使用但是代码报错了不会改,有没有人可以看看
  • ¥15 关于#Java#的问题,如何解决?
  • ¥15 加热介质是液体,换热器壳侧导热系数和总的导热系数怎么算