# Data Races, Mutexes and the Race Detector — Go (Golang)

Source: https://www.skillbyai.com/en/go/c-race

> Shared memory needs synchronisation.

## Find races with -race

A **data race** happens when goroutines access the same variable concurrently and at least one writes, without synchronisation; results become unpredictable. Protect shared state with a `sync.Mutex`, use atomic operations for simple counters, or share by communicating over channels instead. Go's **race detector** (`go run -race`, `go test -race`) instruments memory accesses and reports races at runtime with stack traces; run your tests with it in CI.

## Unsynchronised versus mutex-protected counters, run

I ran this with Go 1.27.1 (`go run -race . > run.log 2>&1` in a module named demo, standard library only). The race detector reports "WARNING: DATA RACE" for the unprotected counter and the program exits with status 66, while the mutex-protected counter correctly reaches 100. Output is trimmed to the key lines.

```go
package main

import (
	"fmt"
	"sync"
)

func main() {
	var wg sync.WaitGroup
	counter := 0
	for range 100 {
		wg.Go(func() { counter++ }) // unsynchronised write from many goroutines
	}
	wg.Wait()

	var mu sync.Mutex
	safe := 0
	for range 100 {
		wg.Go(func() {
			mu.Lock()
			safe++
			mu.Unlock()
		})
	}
	wg.Wait()
	fmt.Println("safe counter:", safe)
}
```

Output:

```
WARNING: DATA RACE
safe counter: 100
exit status 66
```

## Run tests with -race in CI

The detector only finds races in code that actually runs, so combine it with good test coverage.

**Quiz:** What is a data race?

- [ ] A slow network request
- [ ] Two goroutines reading the same constant
- [x] Concurrent access to the same memory with at least one write and no synchronisation
- [ ] A channel with a buffer

*Answer:* Concurrent access to the same memory with at least one write and no synchronisation. Use mutexes, atomics or channels.
