A data race is when two or more goroutines attempt to read and write to the same resource at the same time. Race conditions can create bugs that totally appear random or can be never surface as they corrupt data. Atomic functions and mutexes are a way to synchronize the access of shared resources between goroutines.
- Goroutines need to be coordinated and synchronized.
- When two or more goroutines attempt to access the same resource, we have a data race.
- Atomic functions and mutexes can provide the support we need.
This content is provided by Scott Meyers from his talk in 2014 at Dive:
CPU Caches and Why You Care (30:09-38:30)
-
Thread memory access matters.
-
If your algorithm is not scaling look for false sharing problems.
The Go Memory Model
http://blog.golang.org/race-detector
http://www.goinggo.net/2013/09/detecting-race-conditions-with-go.html
https://golang.org/doc/articles/race_detector.html
Data Race (Go Playground)
Atomic Increments (Go Playground)
Atomic Store/Load (Go Playground)
Mutex (Go Playground)
Read/Write Mutex (Go Playground)
Interface Based Race Condition (Go Playground)
Given the following program, use the race detector to find and correct the data race.
// https://play.golang.org/p/F5DCJTZ6Lm
// Fix the race condition in this program.
package main
import (
"fmt"
"math/rand"
"sync"
"time"
)
// numbers maintains a set of random numbers.
var numbers []int
// init is called prior to main.
func init() {
rand.Seed(time.Now().UnixNano())
}
// main is the entry point for the application.
func main() {
// Number of goroutines to use.
const grs = 3
// wg is used to manage concurrency.
var wg sync.WaitGroup
wg.Add(grs)
// Create three goroutines to generate random numbers.
for i := 0; i < grs; i++ {
go func() {
random(10)
wg.Done()
}()
}
// Wait for all the goroutines to finish.
wg.Wait()
// Display the set of random numbers.
for i, number := range numbers {
fmt.Println(i, number)
}
}
// random generates random numbers and stores them into a slice.
func random(amount int) {
// Generate as many random numbers as specified.
for i := 0; i < amount; i++ {
n := rand.Intn(100)
numbers = append(numbers, n)
}
}
Template (Go Playground) | Answer (Go Playground)
All material is licensed under the Apache License Version 2.0, January 2004.