dongxiao9583 2018-03-14 23:05
浏览 22
已采纳

为什么Goroutines之间的共享变量不会更新

Why does the code snippet below print out 0? However, i is correctly updated to 1 without the for loop.

package main

import (
    "fmt"
    "time"
)

func main() {

    var i uint64
    go func() {
        for {
            i++
        }
    }()

    time.Sleep(time.Second)
    fmt.Println(i)
}

Solution 1

package main

import (
        "fmt"
        "runtime"
        "time"
)

func main() {

        runtime.GOMAXPROCS(1)

        var i uint64
        ch := make(chan bool)
        go func() {
                for {
                        select {
                        case <-ch:
                                return
                        default:
                                i++
                        }
                }
        }()

        time.Sleep(time.Second)
        ch <- true
        fmt.Println(i)
}

Solution 2

package main

import (
        "fmt"
        "runtime"
        "sync"
        "time"
)

func main() {

        runtime.GOMAXPROCS(1)

        var i uint64
        var mx sync.Mutex
        go func() {
                for {
                        mx.Lock()
                        i++
                        mx.Unlock()
                }
        }()

        time.Sleep(time.Second)
        mx.Lock()
        fmt.Println(i)
        mx.Unlock()
}

Solution 3

package main

import (
        "fmt"
        "runtime"
        "sync/atomic"
        "time"
)

func main() {

        runtime.GOMAXPROCS(1)

        var i uint64
        go func() {
                for {
                        atomic.AddUint64(&i, 1)
                        runtime.Gosched()
                }
        }()

        time.Sleep(time.Second)
        fmt.Println(atomic.LoadUint64(&i))
}
  • 写回答

4条回答 默认 最新

  • dongxie9448 2018-03-14 23:43
    关注

    You have a race condition. The results are undefined.

    package main
    
    import (
        "fmt"
        "time"
    )
    
    func main() {
    
        var i uint64
        go func() {
            for {
                i++
            }
        }()
    
        time.Sleep(time.Second)
        fmt.Println(i)
    }
    

    Output:

    $ go run -race racer.go
    ==================
    WARNING: DATA RACE
    Read at 0x00c0000a2010 by main goroutine:
      main.main()
          /home/peter/src/racer.go:18 +0x95
    
    Previous write at 0x00c0000a2010 by goroutine 6:
      main.main.func1()
          /home/peter/src/racer.go:13 +0x4e
    
    Goroutine 6 (running) created at:
      main.main()
          /home/peter/src/racer.go:11 +0x7a
    ==================
    66259553
    Found 1 data race(s)
    exit status 66
    $ 
    

    Reference: Introducing the Go Race Detector

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(3条)

报告相同问题?

悬赏问题

  • ¥15 我想咨询一下路面纹理三维点云数据处理的一些问题,上传的坐标文件里是怎么对无序点进行编号的,以及xy坐标在处理的时候是进行整体模型分片处理的吗
  • ¥15 CSAPPattacklab
  • ¥15 一直显示正在等待HID—ISP
  • ¥15 Python turtle 画图
  • ¥15 关于大棚监测的pcb板设计
  • ¥15 stm32开发clion时遇到的编译问题
  • ¥15 lna设计 源简并电感型共源放大器
  • ¥15 如何用Labview在myRIO上做LCD显示?(语言-开发语言)
  • ¥15 Vue3地图和异步函数使用
  • ¥15 C++ yoloV5改写遇到的问题