Вести с Полей
Канал с советами по современной ИИ разработке. Вступайте!
833 of 1593 menu
◀ ▶

sync.Mutex.Lock

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

Синтаксис

mu.Lock()

Пример базового использования

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

package main import ( "fmt" "sync" ) func main() { var mu sync.Mutex counter := 0 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) }

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

1000

Пример с блокировкой доступа к структуре

Рассмотрим использование мьютекса для защиты доступа к полям структуры:

package main import ( "fmt" "sync" "time" ) type SafeCounter struct { mu sync.Mutex value int } func (c *SafeCounter) Increment() { c.mu.Lock() c.value++ c.mu.Unlock() } func (c *SafeCounter) GetValue() int { c.mu.Lock() defer c.mu.Unlock() return c.value } func main() { counter := &SafeCounter{} for i := 0; i < 5; i++ { go func() { counter.Increment() }() } time.Sleep(time.Millisecond) fmt.Println(counter.GetValue()) }

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

5

Пример взаимной блокировки

Важно правильно использовать метод Lock, чтобы избежать взаимных блокировок. Рассмотрим некорректный пример:

package main import ( "fmt" "sync" ) func main() { var mu1, mu2 sync.Mutex go func() { mu1.Lock() mu2.Lock() fmt.Println("Горутина 1 захватила оба мьютекса") mu2.Unlock() mu1.Unlock() }() go func() { mu2.Lock() mu1.Lock() fmt.Println("Горутина 2 захватила оба мьютекса") mu1.Unlock() mu2.Unlock() }() }

Результат выполнения кода может быть взаимной блокировкой, так как горутины захватывают мьютексы в разном порядке.

"fatal error: all goroutines are asleep - deadlock!"

Пример с использованием defer

Рекомендуется использовать defer для гарантированного освобождения мьютекса:

package main import ( "fmt" "sync" ) func main() { var mu sync.Mutex data := make(map[int]int) var wg sync.WaitGroup for i := 0; i < 10; i++ { wg.Add(1) go func(id int) { defer wg.Done() mu.Lock() defer mu.Unlock() data[id] = id * id }(i) } wg.Wait() mu.Lock() fmt.Println(data) mu.Unlock() }

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

map[0:0 1:1 2:4 3:9 4:16 5:25 6:36 7:49 8:64 9:81]

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

  • метод sync.Mutex.Unlock,
    который освобождает заблокированный мьютекс
  • метод sync.Mutex.TryLock,
    который пытается заблокировать мьютекс без ожидания
  • тип sync.RWMutex,
    который предоставляет более гибкие механизмы блокировки
  • тип sync.WaitGroup,
    который используется для ожидания завершения группы горутин
← →
↑
Мы используем cookie для работы сайта, аналитики и персонализации. Обработка данных происходит согласно Политике конфиденциальности.
принять все настроить отклонить