在Go的HTTP处理程序中的简单竞态条件 – 这真的是一个竞态条件吗?

huangapple go评论91阅读模式
英文:

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.

huangapple
  • 本文由 发表于 2015年8月4日 00:56:23
  • 转载请务必保留本文链接:https://go.coder-hub.com/31792810.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定