猿问

Golang 并发写入变量 - 为什么这段代码有效?

我正在学习 Golang 中与并发相关的问题。我写了一些代码:


package main


import (

    "fmt"

    "time"

)


func incr(num *int) {

    *num = *num + 1


}


func main() {

    var a = 0


    for i := 0; i < 50; i++ {

        go incr(&a)

    }


    incr(&a)


    time.Sleep(1 * time.Second)

    fmt.Println(a)

}

这段代码的结果是:51


在这段代码中,我声明了a在 50 个正在运行的 goroutine 中增加的变量。根据我的阅读和理解,这段代码应该会失败,因为多个 goroutine 正在写入相同的内存地址。在这种情况下,我应该添加sync.Mutex锁来解决这个问题。


代码在操场上可用:https ://play.golang.org/p/Tba9pfpxaHY


您能解释一下这个程序中到底发生了什么吗?


GCT1015
浏览 88回答 1
1回答

心有法竹

你猜怎么了?我运行了您的应用程序,得到了不同的输出:有时,49,有时,有时(有时)。485051如果您在启用竞争检测器 ( go run -race play.go) 的情况下运行您的应用程序,它会告诉您存在数据竞争:==================WARNING: DATA RACERead at 0x00c00009a010 by goroutine 7:&nbsp; main.incr()&nbsp; &nbsp; &nbsp; /home/icza/gows/src/play/play.go:9 +0x3aPrevious write at 0x00c00009a010 by goroutine 6:&nbsp; main.incr()&nbsp; &nbsp; &nbsp; /home/icza/gows/src/play/play.go:9 +0x50Goroutine 7 (running) created at:&nbsp; main.main()&nbsp; &nbsp; &nbsp; /home/icza/gows/src/play/play.go:17 +0x83Goroutine 6 (finished) created at:&nbsp; main.main()&nbsp; &nbsp; &nbsp; /home/icza/gows/src/play/play.go:17 +0x83==================当你有数据竞争时,你的应用程序的行为是未定义的。“看似有时工作”也符合“未定义”行为,但未定义也意味着它也可以做任何其他事情。
随时随地看视频慕课网APP

相关分类

Go
我要回答