← Назад ко всем вопросам

Являются ли операции с Mutex блокирующими

1️⃣ Как кратко ответить

Да, операции с Mutex в Go являются блокирующими. Когда горутина пытается захватить заблокированный Mutex, она будет заблокирована до тех пор, пока Mutex не будет освобожден другой горутиной.

2️⃣ Подробное объяснение темы

Mutex (сокращение от "mutual exclusion" — взаимное исключение) — это примитив синхронизации, который используется для предотвращения одновременного доступа к общим ресурсам несколькими горутинами. В языке Go Mutex предоставляется пакетом sync.

Когда одна горутина захватывает Mutex, другие горутины, которые пытаются захватить тот же Mutex, будут заблокированы до тех пор, пока первый Mutex не будет освобожден. Это означает, что операции с Mutex являются блокирующими.

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

Рассмотрим пример, где несколько горутин пытаются увеличить общий счетчик:

package main
​
import (
	"fmt"
	"sync"
)
​
func main() {
	var mu sync.Mutex
	counter := 0
	var wg sync.WaitGroup
​
	// Запускаем 10 горутин
	for i := 0; i < 10; i++ {
		wg.Add(1)
		go func() {
			defer wg.Done()
​
			// Захватываем Mutex перед изменением общего ресурса
			mu.Lock()
			// Увеличиваем общий счетчик
			counter++
			// Освобождаем Mutex после изменения
			mu.Unlock()
		}()
	}
​
	// Ожидаем завершения всех горутин
	wg.Wait()
	fmt.Println("Final Counter:", counter)
}

Объяснение кода:

  • var mu sync.Mutex: Создаем переменную mu типа sync.Mutex. Это наш Mutex, который будет использоваться для синхронизации доступа к переменной counter.

  • counter := 0: Инициализируем общий счетчик, который будет увеличиваться горутинами.

  • var wg sync.WaitGroup: Создаем WaitGroup, чтобы дождаться завершения всех горутин.

  • for i := 0; i < 10; i++: Запускаем цикл для создания 10 горутин.

  • wg.Add(1): Увеличиваем счетчик WaitGroup на 1 перед запуском каждой горутины, чтобы WaitGroup знал, сколько горутин нужно ожидать.

  • go func() { ... }(): Анонимная функция, которая запускается как горутина.

  • defer wg.Done(): Уменьшаем счетчик WaitGroup на 1, когда горутина завершает выполнение.

  • mu.Lock(): Захватываем Mutex. Если Mutex уже захвачен другой горутиной, текущая горутина будет заблокирована до тех пор, пока Mutex не будет освобожден.

  • counter++: Увеличиваем общий счетчик. Это критическая секция, доступ к которой должен быть синхронизирован.

  • mu.Unlock(): Освобождаем Mutex, позволяя другим горутинам захватить его и выполнить свою критическую секцию.

  • wg.Wait(): Ожидаем завершения всех горутин, чтобы убедиться, что все изменения счетчика завершены до вывода результата.

Mutex используется для обеспечения того, что только одна горутина может изменять общий ресурс в любой момент времени, предотвращая таким образом состояние гонки. Блокирующее поведение Mutex гарантирует, что горутины будут ждать своей очереди для доступа к ресурсу, что делает операции с Mutex блокирующими.

Тема: Конкурентность
Стадия: Tech

🔒 Подпишись на бусти автора и стань Алигатором, чтобы получить полный доступ к функционалу сайта и отслеживать свой прогресс!

Твои заметки