Go: Mutex and Starvation

Vincent
A Journey With Go
Published in
6 min readSep 13, 2019

--

Illustration created for “A Journey With Go”, made from the original Go Gopher, created by Renee French.

ℹ️ This article is based on Go 1.13.

While developing in Golang, a mutex can encounter starvation issues when it consistently tries to acquire a lock that it is never able to get. For this article, we’ll look at a starvation issue affecting Go 1.8 that was solved in Go 1.9.

Starvation

In order to illustrate a starvation situation with a mutex, I will take the example made by Russ Cox about the issue in which they discuss mutex improvement:

This example is based on two goroutines:

  • goroutine 1 holds the lock for a long time and briefly releases it
  • goroutine 2 briefly holds the lock and releases it for a long time

Both have a cycle of 100 microseconds, but since goroutine 1 is constantly requesting the lock, we could expect it will get the lock more often.

Here is an example, done with Go 1.8, of the lock distribution with a loop of 10 iterations:

Lock acquired per goroutine:
g1: 7200216
g2: 10

The mutex has been acquired ten times by the second goroutine, while the first one got it more than seven million times. Let’s analyze what is happening here.

First, goroutine 1 will get the lock and sleep for 100 microseconds. When goroutine 2 tries to acquire the lock, it will be added to the lock’s queue — FIFO order — and the goroutine will go into waiting:

Figure 1 — lock acquisition

Then, when goroutine 1 finishes its work, it will release the lock. This release will notify the queue to wake goroutine 2 up. Goroutine 2 will be marked as runnable and is waiting for the Go Scheduler to be run on a thread:

--

--