为什么竞态检测器在这里报告竞态条件?

我正在使用 Go 竞争检测(-race 参数),它检测到一些我认为不应该报告的竞争条件问题。我创建了这个示例代码来解释我的发现。请不要对此示例的目标发表评论,因为它除了解释问题之外没有其他目标。

这段代码:

var count int

func main() {
    go update()
    for {
        fmt.Println(count)
        time.Sleep(time.Second)
    }
}

func update() {
    for {
        time.Sleep(time.Second)
        count++
    }
}

报告有竞争条件。

虽然这段代码:

var count int
var mutex sync.RWMutex

func main() {
    go update()
    for {
        mutex.RLock()
        fmt.Println(count)
        mutex.RUnlock()
        time.Sleep(time.Second)
    }
}

func update(){
    for {
        time.Sleep(time.Second)
        mutex.Lock()
        count++
        mutex.Unlock()
    }
}

没有报告任何竞争条件问题。

我的问题是为什么?第一个代码中没有错误。main 函数正在读取另一个 go 例程正在更新的变量。这里没有潜在的隐藏错误。第二个代码互斥锁不提供任何不同的行为。

我哪里错了?

回答

您的代码包含一个非常明确的种族。

您的 for 循环正在访问count另一个 goroutine 正在更新它的同时。这就是种族的定义。

main 函数正在读取另一个 go 例程正在更新的变量。

对,就是这样。赛跑就是这样。

第二个代码互斥锁不提供任何不同的行为。

是的,它确实。它防止变量从不同的 goroutines 同时被读取和写入。


以上是为什么竞态检测器在这里报告竞态条件?的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>