Go HTTP Handler中的简单竞争条件 - 这真的是竞争条件吗?

时间:2015-08-03 16:56:23

标签: go race-condition

鉴于下面的代码,我试图了解为什么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中,从而构成数据竞争吗?

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

3 个答案:

答案 0 :(得分:4)

这是一场数据竞赛,但是比赛探测器并没有报告未发生的比赛。您需要确保测试中有并发调用,并确保GOMAXPROCS>1也可以帮助清除它们。

答案 1 :(得分:4)

那是一场竞争条件。 False negatives can happen with the race checker.

竞赛检查器是动态的:不是检查源是否有问题,它只能查看读取和写入是否实际发生而两者之间没有同步操作。您的代码中没有同步操作,但如果在net/http之间出现增量,则会被欺骗。基本上,Its author suggests运行并发压力测试以解决问题:

  
      
  • 写好并发测试
  •   
  • 使用竞赛检测器持续构建
  •   
  • 运行集成测试
  •   
  • 在生产中运行支持种族的金丝雀
  •   

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

答案 2 :(得分:3)

count++是一场数据竞赛。它不是原子地发生的。它与:

相同
count = count + 1

如果竞赛检测器没有看到它,你可能没有足够地击中服务器。

相关问题