In Go (Golang), a mutex (short for "mutual exclusion") is a synchronization primitive used to manage access to shared resources in concurrent programming. When multiple goroutines (Go's lightweight threads) access shared data, a mutex can help prevent race conditions, which occur when two or more goroutines try to read or write to the same variable at the same time.

Whats wrong in the following example -

package main

import (
	"fmt"
	"sync"
)

func main() {
	var wg sync.WaitGroup
	var sum = 0
	for i := 0; i < 10000; i++ {
		wg.Add(1)

		go func() {
			defer wg.Done()
			sum = sum + 1
		}()
	}
	wg.Wait()
	fmt.Print("sum is ", sum)
}

Screenshot 2024-10-21 at 12.59.39 PM.png

Using mutex to fix it

package main

import (
	"fmt"
	"sync"
)

func main() {
	var wg sync.WaitGroup
	var m sync.Mutex

	var sum = 0
	for i := 0; i < 10000; i++ {
		wg.Add(1)

		go func() {
			defer wg.Done()
			defer m.Unlock()
			m.Lock()
			sum = sum + 1
		}()
	}
	wg.Wait()
	fmt.Print("sum is ", sum)
}

Creating a SafeCounter struct

package main

import (
	"fmt"
	"sync"
)

type safeCounter struct {
	m     sync.Mutex
	value int32
}

func main() {
	var wg sync.WaitGroup
	s := safeCounter{
		m:     sync.Mutex{},
		value: 0,
	}

	for i := 0; i < 10000; i++ {
		wg.Add(1)

		go func() {
			defer wg.Done()
			defer s.m.Unlock()
			s.m.Lock()
			s.value++
		}()
	}
	wg.Wait()
	fmt.Print("sum is ", s.value)
}