В чем разница между Mutex и Atomic в Go? Когда что использовать?

Ответ

Mutex (мьютекс) и atomic операции — это два механизма для управления конкурентным доступом к данным, но они работают на разных уровнях и предназначены для разных задач.

Сравнительная таблица

Характеристикаsync/atomicsync.Mutex
УровеньНизкоуровневый, аппаратныйВысокоуровневый, на уровне ОС/рантайма
Что защищаетОтдельные примитивные типы (int32, int64, uintptr, unsafe.Pointer)Произвольные участки кода (критические секции), которые могут содержать сложные структуры данных
Принцип работыИспользует атомарные инструкции процессора (например, Compare-And-Swap)Блокирует горутину, если мьютекс занят, и планировщик переключает её на другую
ПроизводительностьОчень быстрый, без блокировок (lock-free)Медленнее из-за накладных расходов на блокировку и переключение контекста

Когда что использовать?

Используйте atomic для:

  • Простых операций, таких как инкремент/декремент счетчиков, установки флагов или безопасного чтения/записи указателя.
  • Ситуаций, где производительность критически важна и можно обойтись без сложных блокировок.
// Потокобезопасный счетчик
var counter int64
atomic.AddInt64(&counter, 1)

// Безопасное чтение значения
val := atomic.LoadInt64(&counter)

Используйте Mutex для:

  • Защиты сложных структур данных (мапы, слайсы, структуры).
  • Выполнения нескольких операций над данными как единой атомарной транзакции (например, прочитать значение, изменить его и записать обратно).
var mu sync.Mutex
var data = make(map[string]int)

// Защита нескольких операций
mu.Lock()
data["requests"]++
data["last_ts"] = time.Now().Unix()
mu.Unlock()

Вывод: atomic — это легковесный инструмент для простых, атомарных модификаций примитивов. Mutex — более мощный, но и более "тяжелый" механизм для защиты сложных операций и структур данных.