В параллельном программировании на языке Go блокировка мьютекса(sync.Mutex
)иблокировка чтения-записи(sync.RWMutex
)Это достижение потокобезопасности、Основные инструменты для защиты общих ресурсов от гонок。В этой статье в простой и понятной форме будут проанализированы характеристики и использование этих двух замков.,Обсудить распространенные проблемы, распространенные ошибки и решения,И углубите свое понимание с помощью примеров кода.
блокировка мьютекса,Как следует из названия,Убедитесь, что одновременно есть только одинgoroutine
Возможность доступа к защищенным ресурсам。существоватьGoсередина,sync.Mutex
Тип обеспечивает блокировку(Lock()
)и разблокировать(Unlock()
)методдля достижения взаимоисключающего доступа。
var mu sync.Mutex
var sharedResource int
func increment() {
mu.Lock()
sharedResource++
mu.Unlock()
}
func decrement() {
mu.Lock()
sharedResource--
mu.Unlock()
}
Забыл позвонитьUnlock()
методприведет к другимgoroutine
заблокирован навсегда,тупик。Обязательно убедитесь, что каждыйLock()
Все имеют соответствующиеUnlock()
。
gomu.Lock()
// ... сложная логика ...
// Если ты забудешь здесь Unlock()
Решение:следовать“замок-Исправлять-Разблокировать”режим,убеждатьсясуществоватькаждый разLock()
назад Все имеют соответствующиеUnlock()
。использоватьdefer
语句可以убеждаться Разблокироватьдействоватьсуществовать Автоматически выполняется перед возвратом функции,Не забудьте разблокировать:
func increment() {
mu.Lock()
defer mu.Unlock()
sharedResource++
}
Звонил несколько разUnlock()
может привести к гонкам данных илиpanic。каждыйLock()
может быть только Разблокироватьодин раз。
mu.Lock()
sharedResource++
mu.Unlock()
mu.Unlock() // ошибка:Разблокировать повторно
Решение:убеждатьсякаждыйLock()
Существует только один соответствующийUnlock()
。использоватьdefer
можно избежать таких проблем。
блокировка чтения-записисуществоватьблокировка мьютекса Добавлена оптимизация операций чтения на основе。Это позволяет любому количеству читателей(RLock()
)Доступ к ресурсам одновременно,Но писатель(Lock()
)По-прежнему иметь эксклюзивный доступ。sync.RWMutex
предоставилRLock()
、RUnlock()
、Lock()
иUnlock()
метод。
var rwmu sync.RWMutex
var sharedResource string
func reader() {
rwmu.RLock()
fmt.Println(sharedResource)
rwmu.RUnlock()
}
func writer(newValue string) {
rwmu.Lock()
sharedResource = newValue
rwmu.Unlock()
}
sync.RWMutex
Прямое обновление с блокировки чтения на блокировку записи или переход с блокировки записи на блокировку чтения не поддерживается.。Попытка сделать это может привести к взаимоблокировке или гонке данных.。
rwmu.RLock()
// Ошибка: невозможно напрямую перейти с блокировки чтения на блокировку записи.
rwmu.Lock()
Решение:Если вам нужно обновить или понизить версию,Существующие блокировки должны быть сначала сняты.,Тогда приобретите новый тип замка. Обратите внимание, что между освобождением старой блокировки и получением новой блокировки может возникнуть состояние гонки.,Требуется правильная синхронизация.
Блокировки чтения-записи и блокировки мьютексов имеют разные функции и разные сценарии использования. Неправильное использование может привести к снижению производительности или возникновению гонок.
var sharedResource int
var mu sync.Mutex // следует использовать sync.RWMutex
func reader() {
mu.RLock() // ошибка:блокировка мьютекса Нет RLock метод
fmt.Println(sharedResource)
mu.RUnlock()
}
Решение:По режиму доступа к ресурсу(Больше чтения и меньше письма или сбалансированное чтение и письмо.)Выберите правильный тип замка。Для частого чтения、Иногда написанные сцены,Приоритет отдается использованию блокировки чтения-записи.
Понимание и правильное использование блокировки мьютекса(sync.Mutex
)иблокировка чтения-записи(sync.RWMutex
)Безопасно ли писать параллелизмGoОсновы программы。Имейте в виду следующие моменты:
goroutine
доступ к ресурсам,Подходит для сценариев с большим количеством письма или сбалансированным чтением и письмом.defer
语句убеждаться Разблокироватьдействовать的正确执行,Улучшите читаемость и надежность кода.Следуя этим принципам, вы сможете эффективно использовать механизмы блокировки в параллельном программировании на Go и создавать безопасные и эффективные параллельные приложения.