Являются ли атомарные операции в пакете `sync/atomic` блокирующими?

Ответ

Нет, атомарные операции не являются блокирующими. Это низкоуровневые примитивы синхронизации, которые выполняются как единая, неделимая инструкция на уровне процессора. Они lock-free, то есть не используют мьютексы.

Ключевое отличие от мьютексов (sync.Mutex):

  • Мьютекс: Если горутина пытается захватить заблокированный мьютекс, планировщик Go приостанавливает её (блокирует) и переключается на другую горутину. Это может привести к переключению контекста.
  • Атомарная операция: Горутина не блокируется планировщиком. Операция выполняется очень быстро с использованием специальных инструкций процессора (например, Compare-And-Swap). Это позволяет избежать накладных расходов на переключение контекста.

Пример (потокобезопасный счетчик):

import (
    "fmt"
    "sync"
    "sync/atomic"
)

func main() {
    var counter int64
    var wg sync.WaitGroup

    for i := 0; i < 1000; i++ {
        wg.Add(1)
        go func() {
            defer wg.Done()
            // Неблокирующая, безопасная операция инкремента
            atomic.AddInt64(&counter, 1)
        }()
    }

    wg.Wait()
    fmt.Println("Final Counter:", counter) // 1000
}

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

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