原文

数据竞争是指两个或多个 goroutine 尝试同时读取和写入同一资源。 竞争条件可能会产生看起来完全随机的错误,或者在破坏数据时永远不会出现。 原子操作和互斥锁是一种同步 goroutine 之间共享资源访问的方法。

注意:

  1. Goroutines 需要协调和同步。
  2. 当两个或多个 goroutine 试图访问同一个资源时,就会发生数据竞争。
  3. 原子操作和互斥锁可以提供我们需要的支持。

缓存不一致和伪共享

此内容由 Scott Meyers 在 2014 年在 Dive 的演讲中提供:
image.png
缓存不一致和伪共享注意事项:

  1. 线程内访问问题
  2. 如果您的算法没有问题,请关注伪共享方面的问题。

参考链接:
Eliminate False Sharing - Herb Sutter
The Go Memory Model
Introducing the Go Race Detector - Dmitry Vyukov and Andrew Gerrand
Detecting Race Conditions With Go - William Kennedy
Data Race Detector

图解

观察数据竞争的一个例子:
image.png

代码测试:
1、Data Race (Go Playground)
2、Atomic Increments (Go Playground)
3、Mutex (Go Playground)
4、Read/Write Mutex (Go Playground)
5、Map Data Race (Go Playground)

进阶代码测试:
Interface Based Race Condition (Go Playground)

练习:
给定以下程序,使用竞争检测器查找并纠正数据竞争。

  1. // https://play.golang.org/p/F5DCJTZ6Lm
  2. // Fix the race condition in this program.
  3. package main
  4. import (
  5. "fmt"
  6. "math/rand"
  7. "sync"
  8. "time"
  9. )
  10. // numbers maintains a set of random numbers.
  11. var numbers []int
  12. // init is called prior to main.
  13. func init() {
  14. rand.Seed(time.Now().UnixNano())
  15. }
  16. // main is the entry point for the application.
  17. func main() {
  18. // Number of goroutines to use.
  19. const grs = 3
  20. // wg is used to manage concurrency.
  21. var wg sync.WaitGroup
  22. wg.Add(grs)
  23. // Create three goroutines to generate random numbers.
  24. for i := 0; i < grs; i++ {
  25. go func() {
  26. random(10)
  27. wg.Done()
  28. }()
  29. }
  30. // Wait for all the goroutines to finish.
  31. wg.Wait()
  32. // Display the set of random numbers.
  33. for i, number := range numbers {
  34. fmt.Println(i, number)
  35. }
  36. }
  37. // random generates random numbers and stores them into a slice.
  38. func random(amount int) {
  39. // Generate as many random numbers as specified.
  40. for i := 0; i < amount; i++ {
  41. n := rand.Intn(100)
  42. numbers = append(numbers, n)
  43. }
  44. }

模板 (Go Playground) | 参考答案 (Go Playground)