Daaang Amy
open main menu

Mutexes In Go

/ 2 min read
Last updated:

What And Why

A mutex, short for mutual exclusion, locks access to data. With mutexes, we can ensure that our goroutines are not reading or writing to a variable at the same time which could cause the program to panic. AKA crash the entire program.

Mutexes are a part of the Go standard library and can be accessed through the sync library. We can use sync.Mutex.Lock() to block other go routines from accessing data until sync.Mutex.Unlock() is called. These two should always be paired together. Probably a good idea to use defer sync.Mutex.Unlock() each time.

Simple Example:

func main() {
	mu := &sync.Mutex{}
	go someOperation(mu)
}

func someOperation(mu *sync.Mutex) {
	mu.Lock()
	defer mu.Unlock()
	// data manipulation here
}

Read/Write Loop Example

package main

import (
	"fmt"
	"sync"
)

func main() {
	m := map[int]int{}

	// create a mutex
	mu := &sync.Mutex{}

	go writeLoop(m, mu)
	go readLoop(m, mu)

	// stop program from exiting, must be killed
	block := make(chan struct{})
	<-block
}

func writeLoop(m map[int]int, mu *sync.Mutex) {
	for {
		for i := 0; i < 100; i++ {
			mu.Lock()
			m[i] = i
			mu.Unlock()
		}
	}
}

func readLoop(m map[int]int, mu *sync.Mutex) {
	for {
		mu.Lock()
		for k, v := range m {
			fmt.Println(k, "-", v)
		}
		mu.Unlock()
	}
}

RW Mutex - Read/Writer Mutex

The standard library also exposes a sync.RWMutex. This should be used to improve performance if we have a read-intensive process. Use RLock and RUnlock to indicate a reader/writer mutex.

Important!

Maps are not safe for concurrent use. If there are multiple goroutines accessing the same map and at least one of them is writing to the map, a mutex lock must be used. Overall, maps are safe for concurrent read access but not read/write or write/write access.