Ответ
Да, операции с sync.Mutex
в Go являются блокирующими.
Это означает, что когда одна горутина захватывает мьютекс, любая другая горутина, пытающаяся его захватить, будет остановлена (заблокирована) до тех пор, пока мьютекс не будет освобожден.
Основные операции:
mu.Lock()
: Захватывает мьютекс. Если он уже захвачен другой горутиной, текущая горутина блокируется и ждет его освобождения.mu.Unlock()
: Освобождает мьютекс, позволяя другим ожидающим горутинам его захватить.
Пример:
var mu sync.Mutex
var counter int
func increment() {
mu.Lock() // Блокировка: горутина ждет, пока мьютекс не освободится
defer mu.Unlock() // Гарантированное освобождение в конце функции
counter++
}
Ключевые моменты:
- Deadlock (Взаимоблокировка): Попытка повторно заблокировать уже заблокированный той же горутиной мьютекс (
mu.Lock()
->mu.Lock()
) приведет к вечной блокировке. - Правильная разблокировка: Вызов
Unlock()
для мьютекса, который не был заблокирован текущей горутиной, вызоветpanic
. Разблокировать мьютекс должна та же горутина, что его и заблокировала. sync.RWMutex
: Для ситуаций, где есть много читателей и редкие писатели, лучше использоватьRWMutex
. Он позволяет множеству горутин одновременно читать данные (RLock
/RUnlock
), но запись (Lock
/Unlock
) требует эксклюзивного доступа.TryLock
(Go 1.18+): Существует неблокирующий методmu.TryLock()
, который пытается захватить мьютекс и немедленно возвращаетtrue
в случае успеха илиfalse
, если мьютекс уже занят, не блокируя горутину.