围棋比赛条件改变

《 Go in action》关于比赛条件的样本:


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)

    }

}

据说最终计数器的末尾应为2,解释如下:“每个goroutine都会覆盖另一个工作。这在goroutine交换发生时会发生。每个goroutine都会制作自己的counter变量副本,然后进行交换当该goroutine有时间再次执行时,counter变量的值已更改,但goroutine不会更新其副本,而是继续增加其拥有的副本并将其值重新设置为计数器变量,替换了其他goroutine执行的工作。”


我想这是环境原因,我的机器输出4为1.10.3 + win10。我想知道自本书发行以来发生了什么变化?如果我取消注释1,则最终计数器将打印2;如果我取消注释2,则将随机打印2。为什么?


泛舟湖上清波郎朗
浏览 241回答 1
1回答

长风秋雁

这本书是错的。关于数据争用的要点是结果不确定。例如,Final Counter可以是任何值。package mainimport (&nbsp; &nbsp; "fmt"&nbsp; &nbsp; "runtime"&nbsp; &nbsp; "sync")var (&nbsp; &nbsp; counter int&nbsp; &nbsp; wg&nbsp; &nbsp; &nbsp; sync.WaitGroup)func main() {&nbsp; &nbsp; wg.Add(2)&nbsp; &nbsp; go incCounter(1)&nbsp; &nbsp; go incCounter(2)&nbsp; &nbsp; wg.Wait()&nbsp; &nbsp; fmt.Println("Final Counter:", counter)}func incCounter(id int) {&nbsp; &nbsp; defer wg.Done()&nbsp; &nbsp; for count := 0; count < 2; count++ {&nbsp; &nbsp; &nbsp; &nbsp; value := counter&nbsp; &nbsp; &nbsp; &nbsp; //1 fmt.Println("value=",value)&nbsp; &nbsp; &nbsp; &nbsp; runtime.Gosched()&nbsp; &nbsp; &nbsp; &nbsp; value++&nbsp; &nbsp; &nbsp; &nbsp; counter = value&nbsp; &nbsp; &nbsp; &nbsp; //2 fmt.Println("counter=",counter)&nbsp; &nbsp; }}输出:$ go versiongo version devel +65fa2b615b Fri Aug 3 23:35:53 2018 +0000 linux/amd64$ go run racer.goFinal Counter: 4$ go run racer.goFinal Counter: 2$ go run racer.goFinal Counter: 2$ go run racer.goFinal Counter: 2$ go run racer.goFinal Counter: 2$ go run racer.goFinal Counter: 4$ go run racer.goFinal Counter: 2$ go run racer.goFinal Counter: 4$ go run -race racer.go==================WARNING: DATA RACERead at 0x0000005e4600 by goroutine 7:&nbsp; main.incCounter()&nbsp; &nbsp; &nbsp; /home/peter/gopath/src/racer.go:27 +0x6fPrevious write at 0x0000005e4600 by goroutine 6:&nbsp; main.incCounter()&nbsp; &nbsp; &nbsp; /home/peter/gopath/src/racer.go:33 +0x90Goroutine 7 (running) created at:&nbsp; main.main()&nbsp; &nbsp; &nbsp; /home/peter/gopath/src/racer.go:17 +0x89Goroutine 6 (finished) created at:&nbsp; main.main()&nbsp; &nbsp; &nbsp; /home/peter/gopath/src/racer.go:16 +0x68==================Final Counter: 4Found 1 data race(s)exit status 66$
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go