为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

Go
智慧大石 2021-10-25 20:10:18
鉴于下面的代码,我试图理解为什么 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贡献1895条经验 获得超7个赞

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


查看完整回答
反对 回复 2021-10-25
?
皈依舞

TA贡献1851条经验 获得超3个赞

这是一个竞争条件。种族检查器可能会出现假阴性。

竞态检查器是动态的:它不会检查问题的来源,它只能查看读取和写入是否实际发生,两者之间没有同步操作。您的代码中没有同步操作,但如果net/http在增量之间发生了同步操作,它就会被愚弄。 它的作者建议,本质上,运行并发压力测试来解决问题:

  • 编写好的并发测试

  • 使用比赛检测器进行连续构建

  • 运行集成测试

  • 在生产中运行支持竞争的金丝雀

在 Go 1.4 及以下版本中,您还应该确保您的程序在多个内核上运行,例如,runtime.GOMAXPROCS(runtime.NumCPU()). 在 2015 年底左右发布的 Go 1.5 中,GOMAXPROCS 将默认在所有可用内核上运行您的代码。


查看完整回答
反对 回复 2021-10-25
?
蛊毒传说

TA贡献1895条经验 获得超3个赞

count++是一场数据竞赛。它不会以原子方式发生。它与以下内容相同:

count = count + 1

如果比赛检测器没有看到它,您可能没有足够努力地访问服务器。


查看完整回答
反对 回复 2021-10-25
  • 3 回答
  • 0 关注
  • 221 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信