Метод sync.Mutex.Unlock
Метод sync.Mutex.Unlock используется для освобождения
блокировки, захваченной ранее с помощью метода Lock.
После вызова Unlock мьютекс становится доступным для
захвата другими горутинами. Важно вызывать этот метод только
после успешного вызова Lock, иначе произойдет паника.
Обычно Unlock вызывается в конце критической секции,
часто с использованием отложенного вызова defer, чтобы
гарантировать освобождение блокировки даже в случае паники или
преждевременного выхода из функции.
Синтаксис
mu.Unlock()
Пример
Давайте рассмотрим базовый пример использования
Unlock для защиты общего счетчика от гонок данных:
package main
import (
"fmt"
"sync"
)
func main() {
var mu sync.Mutex
var counter int
var wg sync.WaitGroup
for i := 0; i < 1000; i++ {
wg.Add(1)
go func() {
defer wg.Done()
mu.Lock()
counter++
mu.Unlock()
}()
}
wg.Wait()
fmt.Println("Counter:", counter)
}
Результат выполнения кода:
"Counter: 1000"
Пример
Важно использовать defer для вызова Unlock,
чтобы гарантировать освобождение мьютекса даже при возникновении
паники. Рассмотрим этот подход:
package main
import (
"fmt"
"sync"
)
func main() {
var mu sync.Mutex
var data []int
mu.Lock()
defer mu.Unlock()
// Имитация работы с общим ресурсом
data = append(data, 42)
fmt.Println("Data:", data)
// Даже если здесь произойдет паника, мьютекс будет освобожден
// panic("unexpected error")
}
Результат выполнения кода:
"Data: [42]"
Пример
Если попытаться вызвать Unlock для незаблокированного
мьютекса, произойдет паника. Покажем это на примере:
package main
import (
"fmt"
"sync"
)
func main() {
var mu sync.Mutex
mu.Unlock() // Паника: unlock of unlocked mutex
fmt.Println("Эта строка не будет выполнена")
}
Результат выполнения кода:
"fatal error: sync: unlock of unlocked mutex"
Смотрите также
-
метод
sync.Mutex.Lock,
который захватывает блокировку мьютекса -
тип
sync.Mutex,
который представляет взаимное исключение -
метод
sync.Mutex.TryLock,
который пытается захватить блокировку без ожидания -
тип
sync.RWMutex,
который поддерживает разделяемую блокировку