Атомарные операции — это операции над памятью, выполнение которых гарантированно завершается либо полностью, либо не начинается вовсе, и они не могут быть прерваны другими конкурирующими операциями. Они являются неделимыми и потокобезопасными на аппаратном уровне.
В Go пакет sync/atomic предоставляет набор функций для выполнения атомарных операций:
| Функция | Описание |
|---|---|
AddInt32 | Атомарно добавляет значение к int32. |
AddInt64 | Атомарно добавляет значение к int64. |
AddUint32 | Атомарно добавляет значение к uint32. |
AddUint64 | Атомарно добавляет значение к uint64. |
AddUintptr | Атомарно добавляет значение к uintptr. |
CompareAndSwapInt32 | Атомарно сравнивает и обменивает (CAS) int32. |
CompareAndSwapInt64 | Атомарно сравнивает и обменивает (CAS) int64. |
CompareAndSwapUint32 | Атомарно сравнивает и обменивает (CAS) uint32. |
CompareAndSwapUint64 | Атомарно сравнивает и обменивает (CAS) uint64. |
CompareAndSwapUintptr | Атомарно сравнивает и обменивает (CAS) uintptr. |
CompareAndSwapPointer | Атомарно сравнивает и обменивает (CAS) unsafe.Pointer. |
LoadInt32 | Атомарно загружает значение int32. |
LoadInt64 | Атомарно загружает значение int64. |
LoadUint32 | Атомарно загружает значение uint32. |
LoadUint64 | Атомарно загружает значение uint64. |
LoadUintptr | Атомарно загружает значение uintptr. |
LoadPointer | Атомарно загружает значение unsafe.Pointer. |
StoreInt32 | Атомарно сохраняет значение int32. |
StoreInt64 | Атомарно сохраняет значение int64. |
StoreUint32 | Атомарно сохраняет значение uint32. |
StoreUint64 | Атомарно сохраняет значение uint64. |
StoreUintptr | Атомарно сохраняет значение uintptr. |
StorePointer | Атомарно сохраняет значение unsafe.Pointer. |
SwapInt32 | Атомарно обменивает значения int32. |
SwapInt64 | Атомарно обменивает значения int64. |
SwapUint32 | Атомарно обменивает значения uint32. |
SwapUint64 | Атомарно обменивает значения uint64. |
SwapUintptr | Атомарно обменивает значения uintptr. |
SwapPointer | Атомарно обменивает значения unsafe.Pointer. |
Использовать атомарные операции лучше всего в случаях, когда требуется простая, низкоуровневая синхронизация доступа к общим переменным, чаще всего счетчикам или флагам, без использования мьютексов. Они обеспечивают минимальные накладные расходы и лучшую производительность по сравнению с мьютексами в таких сценариях.
Пример использования атомарного счетчика:
go
Пример использования CompareAndSwap:
go
Важно помнить, что атомарные операции работают с примитивными типами данных (целые числа, указатели). Для синхронизации доступа к более сложным структурам данных или выполнения блокирующих операций по-прежнему требуются мьютексы или другие механизмы синхронизации. Чрезмерное или неправильное использование атомарных операций может привести к трудноотлавливаемым ошибкам или снижению производительности.