Ответ
И Mutex
, и RWMutex
— это примитивы синхронизации в Go, предназначенные для защиты разделяемых данных от состояния гонки. Однако они решают эту задачу по-разному и оптимизированы для разных сценариев.
sync.Mutex
(Взаимное исключение)
Mutex
предоставляет эксклюзивную блокировку. Это означает, что только одна горутина может владеть блокировкой в любой момент времени, независимо от того, читает она данные или пишет.
Lock()
: Захватывает блокировку. Если она уже занята, горутина блокируется до её освобождения.Unlock()
: Освобождает блокировку.
sync.RWMutex
(Блокировка чтения-записи)
RWMutex
предоставляет раздельную блокировку, оптимизированную для сценариев, где чтений гораздо больше, чем записей. Правило работы:
- Либо один писатель может захватить блокировку.
- Либо множество читателей могут одновременно захватить блокировку.
Он имеет два типа блокировок:
- Блокировка на запись (
Lock
/Unlock
): Работает как обычныйMutex
— эксклюзивный доступ. - Блокировка на чтение (
RLock
/RUnlock
): Позволяет неограниченному числу горутин одновременно читать данные, но только если нет активной блокировки на запись.
Пример:
var (
rw sync.RWMutex
data int
)
// Множество горутин могут выполнять этот код одновременно
rw.RLock()
fmt.Println("Читаем данные:", data)
rw.RUnlock()
// Только одна горутина может выполнять этот код
rw.Lock()
data++ // Запись
rw.Unlock()
Ключевые отличия и когда что использовать:
Сценарий:
Mutex
: Используйте, когда операции записи происходят часто или когда логика доступа к данным сложна и проще использовать одну эксклюзивную блокировку.RWMutex
: Идеален для структур данных, которые редко изменяются, но часто читаются (например, кеш конфигурации).
Производительность:
RWMutex
может значительно повысить производительность в read-heavy сценариях.- Однако
RWMutex
имеет больше накладных расходов, чемMutex
. Если конкуренция за ресурс низкая или операции записи частые,Mutex
может оказаться быстрее.