Skip to content

Latest commit

 

History

History
113 lines (82 loc) · 3.62 KB

File metadata and controls

113 lines (82 loc) · 3.62 KB

Data Races

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 appear totally random or can never surface as they corrupt data. Atomic functions and mutexes are a way to synchronize the access of shared resources between goroutines.

Notes

  • 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.

Cache Coherency and False Sharing

This content is provided by Scott Meyers from his talk in 2014 at Dive:

CPU Caches and Why You Care (30:09-38:30)
Code Example

figure1

Cache Coherency and False Sharing Notes

  • Thread memory access matters.
  • If your algorithm is not scaling look for false sharing problems.

Links

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

Diagram

View of Data Race in Example1.

Ardan Labs

Code Review

Data Race (Go Playground)
Atomic Increments (Go Playground)
Mutex (Go Playground)
Read/Write Mutex (Go Playground)
Map Data Race (Go Playground)

Advanced Code Review

Interface Based Race Condition (Go Playground)

Exercises

Exercise 1

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.