Sobes.tech
Назад к вопросам
Senior
7

Как шарить память между горутинами? В каких случаях лучше использовать Atomic, а в каких Mutex/RWMutex/SyncMap?

Компании, где спрашивали
plata

Ответ от нейросети

sobes.tech AI

В Go для шаринга памяти между горутинами используют разные механизмы в зависимости от задачи:

  • Atomic (пакет sync/atomic) подходит для простых операций с примитивными типами (int, uint64, указатели), когда нужно быстро и без блокировок изменять или читать значение. Хорош для счётчиков, флагов, где операции атомарны и не требуют сложной логики.

  • Mutex / RWMutex (sync.Mutex, sync.RWMutex) используются, когда нужно защитить доступ к более сложным структурам данных или когда операции не сводятся к простому атомарному изменению. Mutex блокирует доступ, RWMutex позволяет нескольким читателям одновременно, но только одного писателя.

  • Sync.Map — специализированная потокобезопасная карта, оптимизированная для случаев с большим количеством чтений и сравнительно редкими записями. Удобна, когда нужно хранить ключ-значение с конкурентным доступом без ручного управления блокировками.

Выбор:

  • Если нужна высокая производительность и операции простые — atomic.
  • Если данные сложные или операции комплексные — mutex/RWMutex.
  • Если нужно потокобезопасное отображение с удобным API — sync.Map.

Пример использования atomic для счётчика:

var counter int64

func increment() {
    atomic.AddInt64(&counter, 1)
}

func get() int64 {
    return atomic.LoadInt64(&counter)
}

Пример с mutex для защиты среза:

var mu sync.Mutex
var data []int

func add(val int) {
    mu.Lock()
    defer mu.Unlock()
    data = append(data, val)
}

func getAll() []int {
    mu.Lock()
    defer mu.Unlock()
    return append([]int(nil), data...)
}