Race condition и способы их предотвращения
Вопрос
Что такое состояние гонки (race condition)? Какие механизмы в Go помогают их избежать? Как использовать флаг -race для их обнаружения?
Ответ
Race condition - ситуация, когда несколько горутин одновременно обращаются к разделяемым данным, и результат зависит от порядка выполнения. Способы предотвращения: - sync.Mutex/RWMutex для защиты критических секций - Каналы для передачи данных - sync/atomic для атомарных операций - sync.Once для однократной инициализации Флаг -race включает детектор гонок при компиляции.
// Плохо - race condition
var counter int
func increment() {
counter++ // НЕ атомарная операция!
}
// Хорошо - с мьютексом
var (
counter int
mu sync.Mutex
)
func safeIncrement() {
mu.Lock()
defer mu.Unlock()
counter++
}
// Или с атомарными операциями
var atomicCounter int64
func atomicIncrement() {
atomic.AddInt64(&atomicCounter, 1)
}
// Плохо - race condition
var counter int
func increment() {
counter++ // НЕ атомарная операция!
}
// Хорошо - с мьютексом
var (
counter int
mu sync.Mutex
)
func safeIncrement() {
mu.Lock()
defer mu.Unlock()
counter++
}
// Или с атомарными операциями
var atomicCounter int64
func atomicIncrement() {
atomic.AddInt64(&atomicCounter, 1)
}
Дополнительные вопросы
Чем отличаются memory ordering гарантии в Go от других языков?