Тип sync.Mutex
Тип sync.Mutex предоставляет механизм взаимного исключения для защиты критических секций в многопоточных программах на Go. Он позволяет синхронизировать доступ к общим ресурсам, гарантируя, что только одна горутина одновременно может выполнять защищенный участок кода. Основные методы мьютекса — это Lock, который блокирует мьютекс, и Unlock, который освобождает блокировку. Мьютекс должен создаваться с помощью ключевого слова var или через new, и его нулевое значение готово к использованию.
Синтаксис
var mu sync.Mutex
mu.Lock()
// критическая секция
mu.Unlock()
Пример
Давайте рассмотрим базовый пример использования мьютекса для защиты счетчика от состояния гонки:
package main
import (
"fmt"
"sync"
)
func main() {
var mu sync.Mutex
counter := 0
var wg sync.WaitGroup
for i := 0; i < 100; i++ {
wg.Add(1)
go func() {
defer wg.Done()
mu.Lock()
counter++
mu.Unlock()
}()
}
wg.Wait()
fmt.Println(counter)
}
Результат выполнения кода:
100
Пример
Покажем, что происходит, если не использовать мьютекс. В этом случае счетчик может стать меньше ожидаемого значения из-за состояния гонки:
package main
import (
"fmt"
"sync"
)
func main() {
counter := 0
var wg sync.WaitGroup
for i := 0; i < 100; i++ {
wg.Add(1)
go func() {
defer wg.Done()
counter++ // гонка данных
}()
}
wg.Wait()
fmt.Println(counter)
}
Результат выполнения кода (может быть разным):
95
Пример
Мьютекс также можно использовать для защиты структуры данных. В этом примере мы защищаем доступ к карте:
package main
import (
"fmt"
"sync"
)
type SafeMap struct {
mu sync.Mutex
m map[string]int
}
func NewSafeMap() *SafeMap {
return &SafeMap{
m: make(map[string]int),
}
}
func (sm *SafeMap) Set(key string, value int) {
sm.mu.Lock()
defer sm.mu.Unlock()
sm.m[key] = value
}
func (sm *SafeMap) Get(key string) int {
sm.mu.Lock()
defer sm.mu.Unlock()
return sm.m[key]
}
func main() {
safeMap := NewSafeMap()
var wg sync.WaitGroup
for i := 0; i < 10; i++ {
wg.Add(1)
go func(i int) {
defer wg.Done()
key := fmt.Sprintf("key%d", i)
safeMap.Set(key, i)
}(i)
}
wg.Wait()
fmt.Println(safeMap.Get("key5"))
}
Результат выполнения кода:
5
Смотрите также
-
метод
sync.Mutex.Lock,
который блокирует мьютекс для текущей горутины -
метод
sync.Mutex.Unlock,
который разблокирует мьютекс, позволяя другим горутинам захватить блокировку -
метод
sync.Mutex.TryLock,
который пытается захватить блокировку без ожидания -
тип
sync.RWMutex,
который предоставляет блокировку для чтения и записи с разделением