这是Go语言中的竞态条件吗?

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

Is this a race condition in go

问题

  1. func main() {
  2. m := map[string]int{
  3. "foo": 42,
  4. "bar": 1337,
  5. }
  6. go func() {
  7. time.Sleep(1 * time.Second)
  8. tmp := map[string]int{
  9. "foo": 44,
  10. "bar": 1339,
  11. }
  12. m = tmp
  13. }()
  14. for {
  15. val := m["foo"]
  16. fmt.Println(val)
  17. }
  18. }

我在许多包中看到了这段代码。

为什么这不被视为竞态条件?

go run -race . 没有报错。

英文:
  1. func main() {
  2. m := map[string]int{
  3. "foo": 42,
  4. "bar": 1337,
  5. }
  6. go func() {
  7. time.Sleep(1 * time.Second)
  8. tmp := map[string]int{
  9. "foo": 44,
  10. "bar": 1339,
  11. }
  12. m = tmp
  13. }()
  14. for {
  15. val := m["foo"]
  16. fmt.Println(val)
  17. }
  18. }

I saw this in many packages.

Why this is not considered as a race condition?

go run -race . giving no error.

答案1

得分: 3

如@Volker所指出的,这是一个数据竞争。由于只有一个写入操作,很难检测到。这里是一个修改后的示例,可以更容易地触发数据竞争错误:

  1. package main
  2. import (
  3. "fmt"
  4. "time"
  5. )
  6. func main() {
  7. m := map[string]int{
  8. "foo": 42,
  9. "bar": 1337,
  10. }
  11. done := make(chan any)
  12. go func() {
  13. for i := 0; i < 100; i++ {
  14. time.Sleep(time.Microsecond)
  15. tmp := map[string]int{
  16. "foo": 44,
  17. "bar": 1339,
  18. }
  19. m = tmp
  20. }
  21. close(done)
  22. }()
  23. for {
  24. select {
  25. case <-done:
  26. return
  27. default:
  28. val := m["foo"]
  29. fmt.Println(val)
  30. }
  31. }
  32. }
英文:

As pointed out by @Volker, this is a data race. And since there is only one write, it's hard to be detected. Here is a modified demo to make it easy to trigger the data race error:

  1. package main
  2. import (
  3. &quot;fmt&quot;
  4. &quot;time&quot;
  5. )
  6. func main() {
  7. m := map[string]int{
  8. &quot;foo&quot;: 42,
  9. &quot;bar&quot;: 1337,
  10. }
  11. done := make(chan any)
  12. go func() {
  13. for i := 0; i &lt; 100; i++ {
  14. time.Sleep(time.Microsecond)
  15. tmp := map[string]int{
  16. &quot;foo&quot;: 44,
  17. &quot;bar&quot;: 1339,
  18. }
  19. m = tmp
  20. }
  21. close(done)
  22. }()
  23. for {
  24. select {
  25. case &lt;-done:
  26. return
  27. default:
  28. val := m[&quot;foo&quot;]
  29. fmt.Println(val)
  30. }
  31. }
  32. }

huangapple
  • 本文由 发表于 2023年6月1日 18:34:29
  • 转载请务必保留本文链接:https://go.coder-hub.com/76381002.html
匿名

发表评论

匿名网友

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

确定