What is a mutex, what types of mutexes exist, and how are they used?
sobes.tech AI
Answer from AI
Mutex (from the English MUTual EXclusion) is a synchronization primitive used to ensure exclusive access to a shared resource between competing goroutines. It guarantees that at any given moment, only one goroutine can own the mutex and, consequently, access the protected data.
In Go, the sync package provides two main types of mutexes:
-
sync.Mutex: A standard mutex. It providesLock()andUnlock()methods. If the mutex is already locked, callingLock()blocks the current goroutine until it is released.Unlock()releases the mutex.var mu sync.Mutex var counter int func increment() { mu.Lock() // Lock access to counter counter++ mu.Unlock() // Unlock access } -
sync.RWMutex: A read/write mutex. It allows multiple goroutines to read the protected resource simultaneously but only one to write. It providesLock(),Unlock()(for writing),RLock(), andRUnlock()(for reading).var rwMu sync.RWMutex var data []int func readData() { rwMu.RLock() // Lock for reading // Read data fmt.Println(data) rwMu.RUnlock() // Unlock reading } func writeData(val int) { rwMu.Lock() // Lock for writing // Write to data data = append(data, val) rwMu.Unlock() // Unlock writing }
Using mutexes is necessary to prevent race conditions, where multiple goroutines attempt to modify the same data simultaneously, leading to unpredictable results.
Usage rules:
- Call
Lock()before accessing the protected resource. - Call
Unlock()after finishing access. It is recommended to usedefer mu.Unlock()to ensure unlocking even in case of panic. - Do not attempt to lock a mutex that is already locked from the same goroutine (may lead to deadlock).
- Do not attempt to unlock an unlocked mutex.
- When using
RWMutex, useRLock/RUnlockfor read operations andLock/Unlockfor write operations. - Mutexes should not be copied after first use. Pass them by reference or pointer.
Example of using defer:
func safeIncrement() {
mu.Lock()
defer mu.Unlock() // Ensures unlocking
counter++
}