猿问

Go HTTP 处理程序中的简单竞争条件 - 这真的是竞争条件吗?

鉴于下面的代码,我试图理解为什么 Go 竞争检测器 ( go run -race example.go) 不会抱怨竞争条件。


var count int


func main() {

    http.HandleFunc("/a/", func(w http.ResponseWriter, r *http.Request) {

        count++ 

        fmt.Println(count)

    })


    http.HandleFunc("/b/", func(w http.ResponseWriter, r *http.Request) {

        count++

        fmt.Println(count)

    })


    log.Fatal(http.ListenAndServe(":8080", nil))

}

我的理解是 Go HTTP Server 在一个单独的 goroutine 中响应所有请求。考虑到这一点,处理函数对全局计数变量所做的增量是否会发生在与主 goroutine 分开的 goroutine 中,从而构成数据竞争?


如果这不是数据竞赛,我非常想知道原因。


智慧大石
浏览 222回答 3
3回答

人到中年有点甜

这是一场数据竞赛,然而竞赛检测器不会报告没有发生的竞赛。您需要确保测试中存在并发调用,并确保GOMAXPROCS>1也可以帮助清除它们。

皈依舞

这是一个竞争条件。种族检查器可能会出现假阴性。竞态检查器是动态的:它不会检查问题的来源,它只能查看读取和写入是否实际发生,两者之间没有同步操作。您的代码中没有同步操作,但如果net/http在增量之间发生了同步操作,它就会被愚弄。 它的作者建议,本质上,运行并发压力测试来解决问题:编写好的并发测试使用比赛检测器进行连续构建运行集成测试在生产中运行支持竞争的金丝雀在 Go 1.4 及以下版本中,您还应该确保您的程序在多个内核上运行,例如,runtime.GOMAXPROCS(runtime.NumCPU()). 在 2015 年底左右发布的 Go 1.5 中,GOMAXPROCS 将默认在所有可用内核上运行您的代码。

蛊毒传说

count++是一场数据竞赛。它不会以原子方式发生。它与以下内容相同:count = count + 1如果比赛检测器没有看到它,您可能没有足够努力地访问服务器。
随时随地看视频慕课网APP

相关分类

Go
我要回答