Метод sync.Mutex.Unlock

Метод sync.Mutex.Unlock используется для освобождения блокировки, захваченной ранее с помощью метода Lock. После вызова Unlock мьютекс становится доступным для захвата другими горутинами. Важно вызывать этот метод только после успешного вызова Lock, иначе произойдет паника. Обычно Unlock вызывается в конце критической секции, часто с использованием отложенного вызова defer, чтобы гарантировать освобождение блокировки даже в случае паники или преждевременного выхода из функции.

Синтаксис

gomu.Unlock()

Пример

Давайте рассмотрим базовый пример использования Unlock для защиты общего счетчика от гонок данных:

gopackage 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)
}

Результат выполнения кода:

go"Counter: 1000"

Пример

Важно использовать defer для вызова Unlock, чтобы гарантировать освобождение мьютекса даже при возникновении паники. Рассмотрим этот подход:

gopackage 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")
}

Результат выполнения кода:

go"Data: [42]"

Пример

Если попытаться вызвать Unlock для незаблокированного мьютекса, произойдет паника. Покажем это на примере:

gopackage main

import (
  "fmt"
  "sync"
)

func main() {
  var mu sync.Mutex

  mu.Unlock() // Паника: unlock of unlocked mutex
  fmt.Println("Эта строка не будет выполнена")
}

Результат выполнения кода:

go"fatal error: sync: unlock of unlocked mutex"

Смотрите также

  • метод sync.Mutex.Lock,
    который захватывает блокировку мьютекса
  • тип sync.Mutex,
    который представляет взаимное исключение
  • метод sync.Mutex.TryLock,
    который пытается захватить блокировку без ожидания
  • тип sync.RWMutex,
    который поддерживает разделяемую блокировку