The sync
package in Go is essential for writing concurrent programs, providing synchronisation primitives such as
locks to manage access to shared resources.
Locks are fundamental for managing concurrent access to shared resources.
They ensure that only one goroutine can access a resource at a time, preventing data races and ensuring data
consistency.
Two primary types of locks are provided in Go's sync
package: Mutex
and RWMutex
.
A Mutex (mutual exclusion lock) provides exclusive access to a resource.
var mu sync.Mutex
func accessResource() {
mu.Lock() // Lock the mutex before accessing the resource
// Access the shared resource
mu.Unlock() // Unlock the mutex after accessing the resource
}
Lock()
acquires the lock, blocking if necessary until available.Unlock()
releases the lock.- Always unlock the mutex to prevent deadlocks.
RWMutex is a reader/writer mutual exclusion lock allowing concurrent read access but exclusive write access.
var rwmu sync.RWMutex
func readResource() {
rwmu.RLock() // Lock the mutex for reading
// Read the shared resource
rwmu.RUnlock() // Unlock the mutex after reading
}
func writeResource() {
rwmu.Lock() // Lock the mutex for writing
// Write to the shared resource
rwmu.Unlock() // Unlock the mutex after writing
}
- Multiple goroutines can hold a read lock at the same time, but only one can hold a write lock.
RLock()
andRUnlock()
are used for reading,Lock()
andUnlock()
are used for writing.
See package
Locks are crucial when multiple goroutines need to access shared resources but not simultaneously to prevent data races and ensure data consistency.
- Protecting shared data structures.
- Managing access to shared resources like file handles or network connections.
- Deadlocks:
- Forgetting to unlock a mutex or locking it multiple times without unlocking can lead to deadlocks.
- Runtime Panics:
- Unlocking a mutex that is not locked or in the wrong goroutine can cause runtime panics.
- Starvation:
- Excessive use of write locks can starve readers in the case of
RWMutex
.
- Excessive use of write locks can starve readers in the case of
- Always unlock a mutex in the same goroutine that locked it.
- Use
defer
to ensure a mutex is unlocked even if a function exits early. - Prefer
RWMutex
if the resource is read-mostly to allow concurrent read access.