Part 1 , Part 2 , Part 3 , Part 4 , Part 5
In Go, critical sections refer to parts of your code that manipulate a resource which must be accessed by only one goroutine at a time. By using a mutex, you can temporarily lock a critical section, perform the operation, and then unlock it, allowing other goroutines to access the resource. Attempting to lock a critical section in a goroutine will block execution until the lock can be acquired.
Playground: https://go.dev/play/p/OEd7jdOA_Mw
package main
import (
"fmt"
"sync"
)
func main() {
// create a map to store the products of two numbers
// with the numbers in string form as a key
productMap := map[string]int{}
// create a mutex to protect the map
// since only one goroutine can access the map at a time
mu := sync.Mutex{}
wg := sync.WaitGroup{}
// use many goroutines to compute the product of two numbers
for i := 0; i < 10; i++ {
for j := 0; j < 10; j++ {
copyI, copyJ := i, j
wg.Add(1)
go func() {
defer wg.Done()
// compute the product
key := fmt.Sprintf("%d,%d", copyI, copyJ)
product := copyI * copyJ
// this is a critical section
// only one goroutine can access the map at a time
// this is a common pattern to protect a shared resource
// with a mutex
mu.Lock()
productMap[key] = product
mu.Unlock()
}()
}
}
// wait for all the goroutines to finish
wg.Wait()
// print the products from the map
for key, product := range productMap {
fmt.Println(key, product)
}
fmt.Println("Done", len(productMap))
}