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 — локальная установка не требуется.
Все уроки этого курса
- sync.Mutex и sync.RWMutex
- sync.WaitGroup
- sync.Once и sync.Map
- Детектор состязаний и безопасные шаблоны