go · level 3 · unit 4 · lesson 1
- meet it
- guess first
- your turn
- fix it
- nailed it
Tap a green word if you get lost.
meet it
Two goroutines, one variable, at least one writing: a .
When two goroutines use the same variable at the same time and at least one of them writes, you have a data race. count++ looks like one step but is three: read, add one, write back. Two goroutines can both read 5 and both write 6, and one visit is lost.
Races are nasty because the program usually works. It passes on your laptop, then goes wrong on a busy server at 3am. Go ships a to catch them: on your own computer, run go run -race main.go or go test -race, and it reports every race it sees happen.
There are three cures. Do not share: give each goroutine its own slot. Lock: guard the variable with a mutex. Communicate: pass values over a channel, so only one goroutine ever touches the data.
package main
import (
"fmt"
"strings"
"sync"
)
func main() {
logs := []string{"home shop home", "blog", "home home shop"}
counts := make([]int, len(logs))
var wg sync.WaitGroup
for i, log := range logs {
wg.Add(1)
go func(i int, log string) {
defer wg.Done()
counts[i] = strings.Count(log, "home")
}(i, log)
}
wg.Wait()
total := 0
for _, c := range counts {
total += c
}
fmt.Println("home visits:", total)
} This program uses the first cure: every goroutine counts into its own slot, and only main adds them up.
guess first
Here is a race, slowed down by hand. What is the count?
Guess before you run it. Wrong guesses are how you learn, and nothing is marked.
package main
import "fmt"
func main() {
visits := 5
a := visits
b := visits
visits = a + 1
visits = b + 1
fmt.Println(visits)
}
your turn
Your turn. Count the words in every chapter at once.
Write a third chapter of your own. Then fill the slot each goroutine writes, so no two goroutines share a variable. strings.Fields splits text into words.
output
press run to see what happens
fix it
The prices come out as zeros. Can you fix it?
output
press run to see what happens
mainreadswithVATwhile the goroutines may still be writing it. That is a data race.- Nothing may read the results until every goroutine has called
Done. - Swap the last two lines, so
wg.Wait()comes beforefmt.Println.
nailed it
you can spot a data race. :D
- A data race: one variable, same time, at least one write.
count++is three steps, so updates can be lost.- Cure races by not sharing, by locking, or by communicating.
new words in your collection
- data race
- race detector
This lesson isn’t saved. A free account remembers every lesson you finish.