Mutex in Golang With Examples
Last Updated :
21 Apr, 2020
A Mutex is a method used as a locking mechanism to ensure that only one Goroutine is accessing the
critical section of code at any point of time. This is done to prevent race conditions from happening. Sync package contains the Mutex. Two methods defined on Mutex
Any code present between a call to Lock and Unlock will be executed by only one Goroutine.
mutex.Lock()
x = x + 1 // this statement be executed
// by only one Goroutine
// at any point of time
mutex.Unlock()
If one Goroutine already has the lock and if a new Goroutine is trying to get the lock, then the new Goroutine will be stopped until the mutex is unlocked. To understand this concept, let's first understand a program having race conditions.
Program with Race Condition
Here is an example of a program which encounters race condition
C
// Program with race condition
package main
import (
"fmt"
"sync" // to import sync later on
)
var GFG = 0
// This is the function we’ll run in every
// goroutine. Note that a WaitGroup must
// be passed to functions by pointer.
func worker(wg *sync.WaitGroup) {
GFG = GFG + 1
// On return, notify the
// WaitGroup that we’re done.
wg.Done()
}
func main() {
// This WaitGroup is used to wait for
// all the goroutines launched here to finish.
var w sync.WaitGroup
// Launch several goroutines and increment
// the WaitGroup counter for each
for i := 0; i < 1000; i++ {
w.Add(1)
go worker(&w)
}
// Block until the WaitGroup counter
// goes back to 0; all the workers
// notified they’re done.
w.Wait()
fmt.Println("Value of x", GFG)
}
Explanation: In the program above, the
worker function in line no. 12 increments the value of
GFG by 1 and then calls
Done() on the
WaitGroup to inform its completion. The
worker function is called 1000 times. Each of these Goroutines run simultaneously and race condition occurs when trying to increment
GFG in line no. 13 as multiple Goroutines try to access the value of
GFG concurrently. Running the same program multiple times gives different outputs each time because of the race condition.
Remember one thing, if you will check the output of the above program using the online compiler, you might get the same output every time(means no race condition) due to the deterministic nature. So use the local compiler like Visual Studio or CMD to see the results.
Solving the Above Problem Using Mutex
Here is an example of a program which how race condition is fixed.
C
// Program with race condition fixed by mutex
package main
import (
"fmt"
"sync" // to import sync later on
)
var GFG = 0
// This is the function we’ll run in every
// goroutine. Note that a WaitGroup must
// be passed to functions by pointer.
func worker(wg *sync.WaitGroup, m *sync.Mutex) {
// Lock() the mutex to ensure
// exclusive access to the state,
// increment the value,
// Unlock() the mutex
m.Lock()
GFG = GFG + 1
m.Unlock()
// On return, notify the
// WaitGroup that we’re done.
wg.Done()
}
func main() {
// This WaitGroup is used to wait for
// all the goroutines launched here to finish.
var w sync.WaitGroup
// This mutex will synchronize access to state.
var m sync.Mutex
// Launch several goroutines and increment
// the WaitGroup counter for each
for i := 0; i < 1000; i++ {
w.Add(1)
go worker(&w, &m)
}
// Block until the WaitGroup counter
// goes back to 0; all the workers
// notified they’re done.
w.Wait()
fmt.Println("Value of x", GFG)
}
Output:
Value of x 1000
Explanation: Mutex is a struct type and variable
m of type
Mutex is created in line no. 31. The
worker function is changed so that the code which increments
GFG in line no. 18 between
m.Lock() and
m.Unlock(). Now only one Goroutine is allowed to execute this piece of code at any point of time and thus race condition is dealt with.
The address of mutex has to be passed in line no. 37. If the mutex is passed by value instead then each Goroutine will have its own copy of the mutex and the race condition will still persist.
Similar Reads
time.Until() Function in Golang With Examples In Go language, time packages supplies functionality for determining as well as viewing time. The Until() function in Go language holds time value t and is used to evaluate the duration until the time t. Moreover, this function is defined under the time package. Here, you need to import the "time" p
2 min read
io.MultiWriter() Function in Golang with Examples In Go language, io packages supply fundamental interfaces to the I/O primitives. And its principal job is to enclose the ongoing implementations of such king of primitives. The MultiWriter() function in Go language is used to create a writer that copies its writes to each and every given writers, wh
3 min read
io.MultiReader() Function in Golang with Examples In Go language, io packages supply fundamental interfaces to the I/O primitives. And its principal job is to enclose the ongoing implementations of such king of primitives. The MultiReader() function in Go language is used to return a "Reader" that is the logical concatenation of all the stated inpu
3 min read
time.Sleep() Function in Golang With Examples In Go language, time packages supplies functionality for determining as well as viewing time. The Sleep() function in Go language is used to stop the latest go-routine for at least the stated duration d. And a negative or zero duration of sleep will cause this method to return instantly. Moreover, t
3 min read
time.NewTimer() Function in Golang With Examples In Go language, time packages supplies functionality for determining as well as viewing time. The NewTimer() function in Go language is used to create a new Timer that will transmit the actual time on its channel at least after duration "d". Moreover, this function is defined under the time package.
2 min read