Что такое mutex, какие они бывают и как их использовать?
Этот вопрос проверяет знание механизмов синхронизации в Go. Mutex (mutual exclusion) используется для защиты совместного доступа к разделяемым данным между горутинами.
Короткий ответ
Mutex — это механизм синхронизации, который предотвращает одновременный доступ к разделяемым ресурсам несколькими горутинами. В Go есть два типа мьютексов: sync.Mutex (блокирует доступ) и sync.RWMutex (разделяет доступ для чтения и записи). Для работы с мьютексами нужно использовать методы Lock и Unlock.
Длинный ответ
1. Основы Mutex:
Mutex позволяет одной горутине получить эксклюзивный доступ к ресурсу, блокируя доступ для других. Это предотвращает гонки данных (data race) при одновременной записи.
2. Типы мьютексов:
- sync.Mutex: Позволяет одной горутине получить доступ к ресурсу.
- sync.RWMutex: Поддерживает два режима: RLock для одновременного чтения несколькими горутинами и Lock для записи с исключением всех других операций.
Пример использования sync.Mutex:
package main
import (
"fmt"
"sync"
)
func main() {
var mu sync.Mutex
count := 0
increment := func(wg *sync.WaitGroup) {
defer wg.Done()
mu.Lock() // Блокируем доступ
count++ // Увеличиваем счетчик
mu.Unlock() // Разблокируем
}
var wg sync.WaitGroup
for i := 0; i < 5; i++ {
wg.Add(1)
go increment(&wg)
}
wg.Wait()
fmt.Println("Итоговое значение:", count)
}
Пример использования sync.RWMutex:
package main
import (
"fmt"
"sync"
)
func main() {
var mu sync.RWMutex
count := 0
read := func(wg *sync.WaitGroup) {
defer wg.Done()
mu.RLock() // Блокировка для чтения
fmt.Println("Чтение count:", count)
mu.RUnlock()
}
write := func(wg *sync.WaitGroup) {
defer wg.Done()
mu.Lock() // Блокировка для записи
count++
mu.Unlock()
}
var wg sync.WaitGroup
for i := 0; i < 3; i++ {
wg.Add(1)
go write(&wg)
wg.Add(1)
go read(&wg)
}
wg.Wait()
}
3. В каких случаях использовать:
Когда несколько горутин должны взаимодействовать с разделяемыми данными.
Для предотвращения гонок данных при записи.
Когда чтение данных может выполняться конкурентно, но запись требует блокировки (используйте RWMutex).