Ответ
sync.RWMutex
(Read-Write Mutex) — это примитив синхронизации в Go, который обеспечивает более гранулярный контроль доступа к общим данным по сравнению с обычным sync.Mutex
.
Ключевое отличие:
sync.Mutex
: Предоставляет эксклюзивную блокировку. В любой момент времени только одна горутина может владеть блокировкой, независимо от того, читает она данные или пишет.sync.RWMutex
: Разделяет блокировки на чтение и запись. Он позволяет неограниченному числу горутин одновременно читать данные, но только одной горутине — писать. При этом во время записи чтение также невозможно.
Когда использовать RWMutex
?
RWMutex
наиболее эффективен в сценариях, где количество операций чтения значительно превышает количество операций записи. В таких случаях он позволяет достичь большей производительности за счет параллельного выполнения читающих горутин.
Основные методы:
RLock()
/RUnlock()
: Устанавливают и снимают блокировку на чтение (разделяемую).Lock()
/Unlock()
: Устанавливают и снимают блокировку на запись (эксклюзивную).
Пример:
package main
import (
"fmt"
"sync"
"time"
)
// Config представляет собой общую конфигурацию, которую часто читают и редко обновляют
type Config struct {
data map[string]string
mutex sync.RWMutex
}
// Get получает значение по ключу (безопасно для чтения)
func (c *Config) Get(key string) string {
c.mutex.RLock() // Устанавливаем блокировку на чтение
defer c.mutex.RUnlock()
return c.data[key]
}
// Set устанавливает значение (безопасно для записи)
func (c *Config) Set(key, value string) {
c.mutex.Lock() // Устанавливаем эксклюзивную блокировку на запись
defer c.mutex.Unlock()
c.data[key] = value
}
Важное правило: Попытка повысить блокировку с чтения (RLock
) до записи (Lock
) внутри одной горутины приведет к дедлоку. Нельзя вызывать Lock()
, не сняв RLock()
.