How to use Mutex in Golang?


In order to understand why mutex in Go play a significant role to write better and accurate concurrent programs, we must first be aware of the concept called Race Conditions. Let's first understand what Race conditions are and how we can write a concurrent program that features a race condition and how we can then introduce mutex in that program to make it accurate.

Race Condition

A race condition is a condition in which multiple goroutines are trying to access and modify the same resource. It could be the case that one goroutines is trying to increase a value of a particular variable and the other goroutines is trying to access it at the same time, or it could be like multiple goroutines are trying to increase the value of a particular variable at the same time.

It should be noted that race conditions arise only if we have provided the writing permissions for a particular variable. If only read permissions were available, then there wouldn't have been any problem as reading doesn't cause any issues, even if multiple goroutines are trying to read a single value.

Example 1

Now let's suppose that we want to write an application for a local bank where the bank only supports a single functionality of depositing amount into the bank. It could be possible that multiple people are trying to deposit amounts at the same time, and we can denote that case with the help of multiple goroutines.

Consider the code shown below which depicts this case.

package main

import (
   "fmt"
   "sync"
)

var (
   balance int
   wg sync.WaitGroup
)

func Deposit(amount int) {
   balance = balance + amount
   wg.Done()
}

func main() {
   wg.Add(3)
   go Deposit(100)
   go Deposit(200)
   go Deposit(300)
   wg.Wait()

   fmt.Println("Balance is:", balance)
}

In the above example, we can see that there are three goroutines other than the main function goroutine. These three goroutines are calling the deposit function and due to this, there's a race condition, as we have not handled it yet.

One can confirm the existence of a race condition with the help of the "race" flag.

go run -race main.go

Note − The race flag is used to check if any Golang code has Race conditions or not.

Output

Balance is: 600

In order to make the code more accurate and remove this race condition, we make use of Mutex, also known as mutual exclusion, that prevents concurrent processes from accessing critical data while a given process is performing another task.

Example 2

Consider the code shown below in which we have used Mutex in the above code, to remove the Race condition.

package main

import (
   "fmt"
   "sync"
)

var (
   balance int
   wg    sync.WaitGroup
   mu    sync.Mutex
)

func Deposit(amount int) {
   mu.Lock()
   defer mu.Unlock()
   balance = balance + amount
   wg.Done()
}

func main() {
   wg.Add(3)
   go Deposit(100)
   go Deposit(200)
   go Deposit(300)
   wg.Wait()

   fmt.Println("Balance is:", balance)
}

Output

Now, if we run the command, go run -race main.go, then we won't see any race condition mentioned. The output we get is shown below.

Balance is: 600

Updated on: 01-Nov-2021

239 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements