Go HTTP 处理程序中的简单竞争条件 - 这真的是竞争条件吗?
Simple Race Condition in Go HTTP Handler - Is this really a 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 服务器在单独的 goroutine 中响应所有请求。考虑到这一点,处理函数对全局计数变量的增量是否会发生在与主 goroutine 分开的 goroutine 中,从而构成数据竞争?
如果这不是数据竞赛,我很想知道为什么。
count++
是一场数据竞赛。它不会自动发生。等同于:
count = count + 1
如果竞争检测器没有发现它,您可能没有足够努力地攻击服务器。
这是一场数据竞赛,但竞赛检测器不会报告未发生的竞赛。您需要确保测试中存在并发调用,确保 GOMAXPROCS>1
也有助于清除它们。
这是一个竞争条件。 False negatives can happen with the race checker.
竞争检查器是动态的:它不会检查源是否有问题,它只能查看读取和写入是否实际发生,中间没有同步操作。您的代码中没有同步操作,但如果在增量之间的 net/http
中出现同步操作,它将被愚弄。 Its author suggests,本质上,运行宁并发压力测试以解决问题:
- write good concurrent tests
- have continuous build with race detector
- run integration tests
- run race-enabled canaries in production
在 Go 1.4 及以下版本中,您还应确保您的程序 运行 位于多个内核上,例如 runtime.GOMAXPROCS(runtime.NumCPU())
。在 2015 年底左右发布的 Go 1.5 中,GOMAXPROCS 将默认 运行 所有可用内核上的代码。
给出下面的代码,我试图理解为什么 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 服务器在单独的 goroutine 中响应所有请求。考虑到这一点,处理函数对全局计数变量的增量是否会发生在与主 goroutine 分开的 goroutine 中,从而构成数据竞争?
如果这不是数据竞赛,我很想知道为什么。
count++
是一场数据竞赛。它不会自动发生。等同于:
count = count + 1
如果竞争检测器没有发现它,您可能没有足够努力地攻击服务器。
这是一场数据竞赛,但竞赛检测器不会报告未发生的竞赛。您需要确保测试中存在并发调用,确保 GOMAXPROCS>1
也有助于清除它们。
这是一个竞争条件。 False negatives can happen with the race checker.
竞争检查器是动态的:它不会检查源是否有问题,它只能查看读取和写入是否实际发生,中间没有同步操作。您的代码中没有同步操作,但如果在增量之间的 net/http
中出现同步操作,它将被愚弄。 Its author suggests,本质上,运行宁并发压力测试以解决问题:
- write good concurrent tests
- have continuous build with race detector
- run integration tests
- run race-enabled canaries in production
在 Go 1.4 及以下版本中,您还应确保您的程序 运行 位于多个内核上,例如 runtime.GOMAXPROCS(runtime.NumCPU())
。在 2015 年底左右发布的 Go 1.5 中,GOMAXPROCS 将默认 运行 所有可用内核上的代码。