鉴于下面的代码,我试图理解为什么 Go 竞争检测器 ( go run -race example.go) 不会抱怨竞争条件。var count intfunc 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 中,从而构成数据竞争?如果这不是数据竞赛,我非常想知道原因。
3 回答
皈依舞
TA贡献1851条经验 获得超3个赞
这是一个竞争条件。种族检查器可能会出现假阴性。
竞态检查器是动态的:它不会检查问题的来源,它只能查看读取和写入是否实际发生,两者之间没有同步操作。您的代码中没有同步操作,但如果net/http
在增量之间发生了同步操作,它就会被愚弄。 它的作者建议,本质上,运行并发压力测试来解决问题:
编写好的并发测试
使用比赛检测器进行连续构建
运行集成测试
在生产中运行支持竞争的金丝雀
在 Go 1.4 及以下版本中,您还应该确保您的程序在多个内核上运行,例如,runtime.GOMAXPROCS(runtime.NumCPU())
. 在 2015 年底左右发布的 Go 1.5 中,GOMAXPROCS 将默认在所有可用内核上运行您的代码。
蛊毒传说
TA贡献1895条经验 获得超3个赞
count++
是一场数据竞赛。它不会以原子方式发生。它与以下内容相同:
count = count + 1
如果比赛检测器没有看到它,您可能没有足够努力地访问服务器。
- 3 回答
- 0 关注
- 221 浏览
添加回答
举报
0/150
提交
取消