Race condition и способы их предотвращения

К вопросам
Сложный
Concurrency

Вопрос

Что такое состояние гонки (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 от других языков?