Что такое мьютекс, какие типы мьютексов существуют и как их использовать?
Sobes Copilot
Получайте ответы в реальном времени
Ответ от нейросети
sobes.tech AI
Мьютекс (от англ. MUTual EXclusion) — это примитив синхронизации, используемый для обеспечения исключительного доступа к разделяемому ресурсу между конкурирующими горутинами. Он гарантирует, что в любой момент времени только одна горутина может владеть мьютексом и, соответственно, обращаться к защищаемым данным.
В Go пакет sync предоставляет два основных типа мьютексов:
-
sync.Mutex: Стандартный мьютекс. Предоставляет методыLock()иUnlock(). Если мьютекс уже заблокирован, вызовLock()блокирует текущую горутину до тех пор, пока он не будет освобожден.Unlock()разблокирует мьютекс.var mu sync.Mutex var counter int func increment() { mu.Lock() // Блокируем доступ к counter counter++ mu.Unlock() // Разблокируем доступ } -
sync.RWMutex: Мьютекс для чтения/записи. Позволяет множеству горутин одновременно читать защищаемый ресурс, но только одной горутине писать. Предоставляет методыLock(),Unlock()(для записи),RLock()иRUnlock()(для чтения).var rwMu sync.RWMutex var data []int func readData() { rwMu.RLock() // Блокируем для чтения // Чтение data fmt.Println(data) rwMu.RUnlock() // Разблокируем чтение } func writeData(val int) { rwMu.Lock() // Блокируем для записи // Запись в data data = append(data, val) rwMu.Unlock() // Разблокируем запись }
Использование мьютексов необходимо для предотвращения состояний гонки (race conditions), когда несколько горутин одновременно пытаются модифицировать одни и те же данные, приводя к непредсказуемым результатам.
Правила использования:
- Вызывать
Lock()перед доступом к защищаемому ресурсу. - Вызывать
Unlock()после завершения доступа. Рекомендуется использоватьdefer mu.Unlock()для гарантии разблокировки даже в случае паники. - Не пытаться блокировать уже заблокированный мьютекс из той же горутины (может привести к дедлоку).
- Не пытаться разблокировать незаблокированный мьютекс.
- При использовании
RWMutex, использоватьRLock/RUnlockдля операций чтения иLock/Unlockдля операций записи. - Мьютексы не должны копироваться после первого использования. Передавайте их по ссылке или указателю.
Пример использования defer:
func safeIncrement() {
mu.Lock()
defer mu.Unlock() // Гарантирует разблокировку
counter++
}