РЕПЕТИТОР математика физика информатика
Для школьников и студентов. Подтягивание пробелов. ЦЭ, ЦТ, ОГЭ, ЕГЭ.
Идет набор на ЛЕТО. Жмите для подробностей:)
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 для работы сайта, аналитики и персонализации. Обработка данных происходит согласно Политике конфиденциальности.
принять все настроить отклонить