How to Use sync.Mutex in Go for Safe Concurrent Access
In Go, use
sync.Mutex to protect shared data from concurrent access by locking it with Lock() before accessing and unlocking with Unlock() after. This ensures only one goroutine can access the critical section at a time, preventing race conditions.Syntax
The sync.Mutex type provides two main methods: Lock() and Unlock(). You create a Mutex variable, then call Lock() before accessing shared data and Unlock() after you're done.
This pattern ensures only one goroutine can enter the critical section at a time.
go
var mu sync.Mutex mu.Lock() // critical section: access shared data safely mu.Unlock()
Example
This example shows two goroutines incrementing a shared counter safely using sync.Mutex. The mutex prevents race conditions by allowing only one goroutine to update the counter at a time.
go
package main import ( "fmt" "sync" ) func main() { var mu sync.Mutex counter := 0 var wg sync.WaitGroup increment := func() { defer wg.Done() for i := 0; i < 1000; i++ { mu.Lock() counter++ mu.Unlock() } } wg.Add(2) go increment() go increment() wg.Wait() fmt.Println("Final counter value:", counter) }
Output
Final counter value: 2000
Common Pitfalls
- Forgetting to
Unlock()afterLock()causes deadlocks, freezing your program. - Using
Mutexincorrectly by locking multiple times without unlocking can also deadlock. - Not using a mutex when accessing shared data leads to race conditions and unpredictable results.
Always use defer mu.Unlock() right after mu.Lock() to avoid forgetting to unlock.
go
var mu sync.Mutex // Wrong: forgetting to unlock causes deadlock mu.Lock() // critical section // mu.Unlock() missing here // Right way: mu.Lock() defer mu.Unlock() // critical section
Quick Reference
sync.Mutex Cheat Sheet:
mu.Lock(): Acquire the lock, blocks if already locked.mu.Unlock(): Release the lock.- Use
defer mu.Unlock()immediately after locking to ensure unlock. - Protect shared variables by locking before access and unlocking after.
- Mutexes prevent race conditions in concurrent programs.
Key Takeaways
Use sync.Mutex to protect shared data from concurrent access in Go.
Always call Lock() before accessing shared data and Unlock() after.
Use defer Unlock() immediately after Lock() to avoid deadlocks.
Failing to unlock or not using mutex causes deadlocks or race conditions.
Mutexes ensure only one goroutine accesses critical sections at a time.