英文:
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中响应所有请求。在这种情况下,处理函数对全局变量count
的递增操作是否发生在与主goroutine分离的goroutine中,从而构成数据竞争?
如果这不是数据竞争,我非常想知道原因。
英文:
Given the code below, I'm trying to understand WHY the Go race detector (go run -race example.go
) does not complain about a race condition.
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))
}
It's my understanding that the Go HTTP Server responds to all requests in a separate goroutine. With that in mind, would not the increments made to the global count variable by the handler functions happen in a goroutine that is separate from the main goroutine and thus, constitute a data race?
If this is not a data race, I'd very much like to know why.
答案1
得分: 6
这是一个数据竞争,但是竞争检测器不会报告没有发生的竞争。你需要确保在你的测试中存在并发调用,并且确保 GOMAXPROCS>1
可以帮助找出它们。
英文:
This is a data race, the race detector however does not report races that don't happen. You need to make sure that there are concurrent calls in your test, and ensuring GOMAXPROCS>1
can help flush them out as well.
答案2
得分: 4
这是一个竞态条件。竞态检查器可能会出现错误的负面结果。
竞态检查器是动态的:它不会检查源代码中的问题,而是只能看到读取和写入是否实际发生,并且之间没有同步操作。在你的代码中没有同步操作,但如果在net/http
之间发生了一个同步操作,它就会被欺骗。它的作者建议,基本上是运行并发压力测试来摆脱问题:
- 编写良好的并发测试
- 持续构建并使用竞态检测器
- 运行集成测试
- 在生产环境中运行启用了竞态检测的金丝雀版本
在Go 1.4及以下版本中,你还应确保你的程序在多个核心上运行,例如使用runtime.GOMAXPROCS(runtime.NumCPU())
。在预计于2015年底发布的Go 1.5中,默认情况下,GOMAXPROCS将在所有可用的核心上运行你的代码。
英文:
That's a race condition. False negatives can happen with the race checker.
The race checker is dynamic: rather than checking the source for problems, it only can only see if read and a write actually occur with no sync operation in between. There's no synchronizing operation in your code, but if one occurs in net/http
between the increments, it'll be fooled. Its author suggests, essentially, running concurrent stress tests to shake out problems:
> * write good concurrent tests
- have continuous build with race detector
- run integration tests
- run race-enabled canaries in production
In Go 1.4 and below, you should also make sure your program runs on more than one core with, e.g., runtime.GOMAXPROCS(runtime.NumCPU())
. In Go 1.5, to be released around the end of 2015, GOMAXPROCS will run your code on all available cores by default.
答案3
得分: 3
count++
是一个数据竞争。它不是原子操作。它与以下代码等效:
count = count + 1
如果竞争检测器没有检测到它,那可能是因为你没有对服务器施加足够大的压力。
英文:
count++
is a data race. It does not happen atomically. It is the same as:
count = count + 1
If the race detector doesn't see it, you probably are not hitting the server hard enough.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论