Что такое mutex, какие они бывают и как их использовать?

Этот вопрос проверяет знание механизмов синхронизации в Go. Mutex (mutual exclusion) используется для защиты совместного доступа к разделяемым данным между горутинами.

Короткий ответ

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

Длинный ответ

1. Основы Mutex:
 

Mutex позволяет одной горутине получить эксклюзивный доступ к ресурсу, блокируя доступ для других. Это предотвращает гонки данных (data race) при одновременной записи.

2. Типы мьютексов:

- sync.Mutex: Позволяет одной горутине получить доступ к ресурсу.

- sync.RWMutex: Поддерживает два режима: RLock для одновременного чтения несколькими горутинами и Lock для записи с исключением всех других операций.

 

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

package main

import (
    "fmt"
    "sync"
)

func main() {
    var mu sync.Mutex
    count := 0

    increment := func(wg *sync.WaitGroup) {
        defer wg.Done()
        mu.Lock()   // Блокируем доступ
        count++     // Увеличиваем счетчик
        mu.Unlock() // Разблокируем
    }

    var wg sync.WaitGroup
    for i := 0; i < 5; i++ {
        wg.Add(1)
        go increment(&wg)
    }

    wg.Wait()
    fmt.Println("Итоговое значение:", count)
}

 

Пример использования sync.RWMutex:

package main

import (
    "fmt"
    "sync"
)

func main() {
    var mu sync.RWMutex
    count := 0

    read := func(wg *sync.WaitGroup) {
        defer wg.Done()
        mu.RLock() // Блокировка для чтения
        fmt.Println("Чтение count:", count)
        mu.RUnlock()
    }

    write := func(wg *sync.WaitGroup) {
        defer wg.Done()
        mu.Lock() // Блокировка для записи
        count++
        mu.Unlock()
    }

    var wg sync.WaitGroup
    for i := 0; i < 3; i++ {
        wg.Add(1)
        go write(&wg)
        wg.Add(1)
        go read(&wg)
    }

    wg.Wait()
}

 

3. В каких случаях использовать:

Когда несколько горутин должны взаимодействовать с разделяемыми данными.

Для предотвращения гонок данных при записи.

Когда чтение данных может выполняться конкурентно, но запись требует блокировки (используйте RWMutex).

Уровень

  • Рейтинг:

    3

  • Сложность:

    8

Навыки

  • Golang

Ключевые слова

Подпишись на Golang Developer в телеграм