Ответ
Пакет atomic
в Go предоставляет низкоуровневые атомарные операции, которые позволяют безопасно работать с общими данными из нескольких горутин без использования мьютексов.
Атомарная операция гарантированно выполняется целиком, без прерывания со стороны планировщика или других горутин, обеспечивая целостность данных на аппаратном уровне.
Когда использовать atomic
:
Его стоит использовать для простых, коротких операций над примитивными типами, таких как:
- Инкремент/декремент счетчиков.
- Чтение/запись флагов или конфигурационных параметров.
- Реализация lock-free алгоритмов.
Они являются высокопроизводительной альтернативой мьютексам для таких простых сценариев.
Пример атомарного счетчика:
import "sync/atomic"
var counter int64
// Безопасно увеличивает счетчик из любой горутины
func increment() {
atomic.AddInt64(&counter, 1)
}
// Безопасно читает значение счетчика
func get() int64 {
return atomic.LoadInt64(&counter)
}
Ключевые операции:
Add
: Атомарное сложение (или вычитание при передаче отрицательного числа).Load
: Атомарное чтение значения.Store
: Атомарная запись значения.Swap
: Атомарная замена значения на новое с возвратом старого.CompareAndSwap
(CAS): Атомарно сравнивает значение с ожидаемым и, если они совпадают, заменяет его новым. Возвращаетtrue
в случае успеха. Это основа для реализации многих lock-free алгоритмов.
Ограничения:
- Работает только с числовыми примитивами (
int32
,int64
,uint32
,uint64
,uintptr
) иunsafe.Pointer
. - Не подходит для синхронизации сложных операций, затрагивающих несколько переменных. В таких случаях следует использовать мьютексы (
sync.Mutex
).