Essential Go Mutex  Edit on GitHub      File Issue

Detecting races

When you don’t use sync.Mutex to ensure exclusive access to data between goroutines or forget to lock in parts of the program, you’ll get data races.

Data races might lead to memory corruption or crashes.

Go makes it easy to instrument the code with additional checks that are very likely to catch data races.

Use -race flag to go build or go run.

Here’s a program with intentional data races.

When you run it with go run -race data_race.go the runtime will notice memory corruption.

var (
	n int
)

func main() {
	var wg sync.WaitGroup
	nCPU := runtime.NumCPU()
	nIter := 100
	for i := 0; i < nCPU; i++ {
		wg.Add(1)
		go func() {
			defer wg.Done()
			for j := 0; j < nIter; j++ {
				n++
				time.Sleep(time.Microsecond * 10)
			}
		}()
	}
	wg.Wait()
	fmt.Printf("n is: %d, expected: %d\n", n, nCPU*nIter)
}
==================
WARNING: DATA RACE
Read at 0x0000011d9318 by goroutine 15:
  main.main.func1()
      /books/go/0230-mutex/data_race.go:25 +0x6d

Previous write at 0x0000011d9318 by goroutine 6:
  main.main.func1()
      /books/go/0230-mutex/data_race.go:25 +0x89

Goroutine 15 (running) created at:
  main.main()
      /books/go/0230-mutex/data_race.go:22 +0xcf

Goroutine 6 (running) created at:
  main.main()
      /books/go/0230-mutex/data_race.go:22 +0xcf
==================
==================
WARNING: DATA RACE
Read at 0x0000011d9318 by goroutine 14:
  main.main.func1()
      /books/go/0230-mutex/data_race.go:25 +0x6d

Previous write at 0x0000011d9318 by goroutine 6:
  main.main.func1()
      /books/go/0230-mutex/data_race.go:25 +0x89

Goroutine 14 (running) created at:
  main.main()
      /books/go/0230-mutex/data_race.go:22 +0xcf

Goroutine 6 (running) created at:
  main.main()
      /books/go/0230-mutex/data_race.go:22 +0xcf
==================
n is: 628, expected: 800
Found 2 data race(s)
exit status 66

This examples shows that memory for variable n is corrupted because the final value of n is not what we expect.

It also shows that instrumentation added with -race can catch memory corruption and points out which part of program caused the corruption.

When to use -race

Additional instrumentation added by -race flag makes the program slower so it’s not usually used when compiling shipping binaries.

It’s a good idea to use on your CI (continous integration) servers when running your test suite.

  ↑ ↓ to navigate     ↵ to select     Esc to close