Ответ
Пакет sync/atomic
предоставляет низкоуровневые атомарные операции (такие как сложение, загрузка, сохранение, сравнение и замена), которые выполняются как единая, неделимая инструкция процессора. Это позволяет безопасно изменять разделяемые данные из нескольких горутин без использования блокировок (mutex
).
Ключевые преимущества:
- Производительность: Атомарные операции значительно быстрее мьютексов, так как они не вызывают блокировку потока ОС и переключение контекста.
- Lock-free алгоритмы: Позволяют создавать неблокирующие алгоритмы для высококонкурентных сценариев.
Основные сценарии использования:
- Счётчики производительности: Безопасное увеличение/уменьшение счётчиков.
- Флаги состояния: Атомарное изменение флагов (например,
isDone
). - Безопасная однократная инициализация: С помощью
atomic.StorePointer
иatomic.LoadPointer
.
Пример: Атомарный счётчик
import (
"fmt"
"sync"
"sync/atomic"
)
func main() {
var counter int64
var wg sync.WaitGroup
// Запускаем 1000 горутин, каждая увеличивает счётчик 100 раз
for i := 0; i < 1000; i++ {
wg.Add(1)
go func() {
defer wg.Done()
for j := 0; j < 100; j++ {
atomic.AddInt64(&counter, 1)
}
}()
}
wg.Wait()
fmt.Println("Итоговое значение счётчика:", counter) // Ожидаемый результат: 100000
}
Atomic vs. Mutex
atomic
: Используйте для простых операций над примитивными типами (int32
,int64
,uintptr
,unsafe.Pointer
). Идеально для счётчиков, флагов.sync.Mutex
: Используйте для защиты сложных структур или для выполнения нескольких операций как единой транзакции. Мьютекс блокирует доступ ко всему защищаемому участку кода для других горутин.