0Pricing
Go Academy · Урок

sync.Mutex и sync.RWMutex

Шаблоны блокировок и блокировок чтения-записи

«sync.Mutex и sync.RWMutex» — бесплатный урок Go Academy на CoddyKit. Это урок 1 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Go Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Go Academy содержит 4 уроков всего.

Зачем нужны мьютексы

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

Основы sync.Mutex

Захватывайте блокировку перед чтением или записью общего состояния, а после этого вызывайте Unlock. Используйте defer, чтобы гарантировать снятие блокировки даже в случае аварийного завершения функции.

var mu sync.Mutex
var counter int

func inc() {
    mu.Lock()
    defer mu.Unlock()
    counter++
}

Встраивание мьютекса в структуру

Встраивайте мьютекс в структуру, которую он защищает. По соглашению мьютекс объявляют непосредственно перед полями, доступ к которым он защищает.

type SafeCounter struct {
    mu sync.Mutex
    v  map[string]int
}
func (c *SafeCounter) Inc(key string) {
    c.mu.Lock()
    defer c.mu.Unlock()
    c.v[key]++
}

Не копируйте мьютекс

Мьютекс нельзя копировать после первого использования. Передавайте его по указателю или встраивайте в структуру, передаваемую по указателю. Инструмент go vet обнаруживает копии.

sync.RWMutex

sync.RWMutex разрешает одновременно выполнять чтение нескольким горутинам, но допускает только одного записывающего участника. Используйте его, когда чтения преобладают, а записи выполняются редко, чтобы повысить пропускную способность.

var rw sync.RWMutex
var data map[string]int

func read(k string) int {
    rw.RLock()
    defer rw.RUnlock()
    return data[k]
}
func write(k string, v int) {
    rw.Lock()
    defer rw.Unlock()
    data[k] = v
}

RLock и Lock

RLock захватывает блокировку для чтения (общую), а Lock — блокировку для записи (эксклюзивную). Ожидающая блокировка для записи не позволяет захватывать новые блокировки для чтения, предотвращая голодание записывающего участника.

TryLock (Go 1.18+)

mu.TryLock() захватывает блокировку только в том случае, если она сейчас свободна, и возвращает логическое значение. Это полезно, когда блокировка недопустима.

if mu.TryLock() {
    defer mu.Unlock()
    // critical section
}

Взаимные блокировки

Взаимная блокировка возникает, когда горутина A удерживает блокировку 1 и ждёт блокировку 2, а горутина B удерживает блокировку 2 и ждёт блокировку 1. Всегда захватывайте блокировки в одном и том же порядке и делайте критические секции короткими.

Зернистость блокировок

Грубая блокировка упрощает понимание программы, но снижает параллелизм. Мелкозернистые блокировки повышают пропускную способность, но увеличивают сложность и риск взаимных блокировок. Начинайте с грубой блокировки и оптимизируйте её, если профилирование покажет конкуренцию за ресурс.

Мьютекс или канал

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

Интерфейс sync.Locker

sync.Locker — это интерфейс с методами Lock и Unlock. И Mutex, и RWMutex реализуют его, поэтому вспомогательные функции могут принимать любой из этих типов.

Быстрая проверка

Когда следует использовать sync.RWMutex вместо sync.Mutex?

Повторение: мьютекс и RWMutex

Основные моменты:

  • Мьютекс сериализует доступ; всегда откладывайте вызов Unlock
  • Не копируйте мьютекс после первого использования
  • RWMutex: несколько читателей OR один писатель
  • Захватывайте блокировки в одном и том же порядке, чтобы избежать взаимных блокировок

Часто задаваемые вопросы

Урок «sync.Mutex и sync.RWMutex» бесплатный?

Да — полный текст урока «sync.Mutex и sync.RWMutex» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Go Academy, подпишись на CoddyKit PRO. Курс Go Academy содержит 4 уроков всего.

Чему я научусь в уроке «sync.Mutex и sync.RWMutex»?

Шаблоны блокировок и блокировок чтения-записи Ты практикуешь Go Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.

Нужен ли мне опыт, чтобы начать Go Academy?

Предыдущий опыт не требуется. Go Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 1 из 4.

Сколько времени занимает урок «sync.Mutex и sync.RWMutex»?

Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.

Можно ли писать и запускать код в этом уроке Go Academy?

Да. Каждый урок Go Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.

Все уроки этого курса

  1. sync.Mutex и sync.RWMutex
  2. sync.WaitGroup
  3. sync.Once и sync.Map
  4. Детектор состязаний и безопасные шаблоны
← Назад к Go Academy