Golang Mutexes – What Is RWMutex For?
Tags: engineering, go, programming, concurrency
Published: 2020-03-19 12:39:26

---
title: Golang Mutexes –  What Is RWMutex For?
published: true
date: 2020-03-19 12:36:54 UTC
tags: engineering,golang,programming,concurrency
canonical_url: https://qvault.io/2020/03/19/golang-mutexes-what-is-rwmutex-for/?utm_source=rss&utm_medium=rss&utm_campaign=golang-mutexes-what-is-rwmutex-for
---

![](https://i1.wp.com/qvault.io/wp-content/uploads/2020/03/exclude.png?w=742&ssl=1)

Golang is King when it comes to concurrency. No other language has so many tools right of-of the box, and one of those tools is the standard library’s [sync.Mutex{}](https://golang.org/pkg/sync/).

## What Problem Do Mutexes Solve?

We don’t want multiple threads accessing the same memory at the same time. In concurrent programming, we have many different threads (or in Go, [goroutines](https://tour.golang.org/concurrency/1)) that all potentially have access to the same variables in memory.

One case that mutexes help us avoid is the **concurrent read/write problem**. This occurs when one thread is **writing** to a variable while another variable is concurrently **reading** from that same variable. The program will panic because the reader could be reading bad data that is being mutated in place.

## What Is A Mutex?

Mutex is short for mutual exclusion. Mutexes keep track of which thread has access to a variable at any given time.

![](https://i1.wp.com/qvault.io/wp-content/uploads/2020/03/download.png?w=742&ssl=1)

Let’s see some examples! Consider the following program:

```
package main

import (
	"fmt"
)

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

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

func writeLoop(m map[int]int) {
	for {
		for i := 0; i < 100; i++ {
			m[i] = i
		}
	}
}

func readLoop(m map[int]int) {
	for {
		for k, v := range m {
			fmt.Println(k, "-", v)
		}
	}
}

```

The program creates a map, then starts 2 goroutines which both have access to the map. One goroutine continuously mutates the values stored in the map, while the other prints the values it finds in the map.

If we run the program, we get the following output:

```
fatal error: concurrent map iteration and map write
```

In Go, it isn’t safe to read-from and write-to a map at the same time.

## Mutexes To The Rescue

```
package main

import (
	"fmt"
	"sync"
)

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

	mux := &sync.Mutex{}

	go writeLoop(m, mux)
	go readLoop(m, mux)

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

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

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

In the code above we add a **sync.Mutex{}** and name it mux. In the write loop, we **Lock()** the mutex before writing, and **Unlock()** it when we are done. This ensures that no other threads can **Lock()** the mutex while we have it locked – those threads will block and wait until we **Unlock()**.

In the reading loop we **Lock()** before iterating over the map, and likewise **Unlock()** when we are done.

## RWMutex – Safely Allow Multiple Readers

Maps are safe for concurrent read access, just not concurrent read/write or write/write access. A read/write mutex allows all the readers to access the map at the same time, but a writer will lock out everyone else.

```
package main

import (
	"fmt"
	"sync"
)

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

	mux := &sync.RWMutex{}

	go writeLoop(m, mux)
	go readLoop(m, mux)
	go readLoop(m, mux)
	go readLoop(m, mux)
	go readLoop(m, mux)

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

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

func readLoop(m map[int]int, mux *sync.RWMutex) {
	for {
		mux.RLock()
		for k, v := range m {
			fmt.Println(k, "-", v)
		}
		mux.RUnlock()
	}
}

```

By using a [sync.RWMutex](https://golang.org/pkg/sync/#RWMutex), our program becomes more efficient. We can have as many readLoops as we want to access our data, but we can assure that the writers have exclusive access.

## Thanks For Reading

Hit me up on twitter [@wagslane](https://twitter.com/wagslane) if you have any questions or comments.

Lane on Dev.to: [wagslane](https://dev.to/wagslane)

The post [Golang Mutexes – What Is RWMutex For?](https://qvault.io/2020/03/19/golang-mutexes-what-is-rwmutex-for/) appeared first on [Qvault](https://qvault.io).