Пакет atomic
Обзор
Пакет atomic предоставляет примитивы атомарной памяти низкого уровня, полезные для реализации алгоритмов синхронизации.
Для правильного использования этих функций требуется большая осторожность. За исключением специальных приложений низкого уровня, синхронизация лучше выполняется с помощью каналов или средств пакета sync. Разделяйте память с помощью обмена данными; не обменивайтесь данными через общую память.
Операция замены, реализованная функциями SwapT, является атомарным эквивалентом:
old = *addr *addr = new return old
Операция сравнения и обмена, реализованная функциями CompareAndSwapT, является атомарным эквивалентом:
if *addr == old {
*addr = new
return true
}
return false
Операция сложения, реализованная функциями AddT, является атомарным эквивалентом:
*addr += delta return *addr
Операции загрузки и сохранения, реализованные функциями LoadT и StoreT, являются атомарными эквивалентами «return *addr» и «*addr = val» соответственно.
В терминологии модели памяти Go, если эффект атомарной операции A наблюдается атомарной операцией B, то A «синхронизируется перед» B. Кроме того, все атомарные операции, выполняемые в программе, ведут себя так, как будто они выполняются в некотором последовательно-согласованном порядке. Это определение обеспечивает те же семантики, что и атомарные операции C++ с последовательной согласованностью и переменные volatile в Java.
Индекс
Файлы пакета
doc.gotype.govalue.go
func AddInt32
func AddInt32(addr *int32, delta int32) (new int32)
AddInt32 атомарно добавляет delta к *addr и возвращает новое значение. Рассмотрите использование более удобного и менее подверженного ошибкам Int32.Add вместо него.
func AddInt64
func AddInt64(addr *int64, delta int64) (new int64)
AddInt64 атомарно добавляет delta к *addr и возвращает новое значение. Рассмотрите использование более удобного и менее подверженного ошибкам Int64.Add вместо него (особенно если вы нацеливаетесь на 32-битные платформы; см. раздел об ошибках).
func AddUint32
func AddUint32(addr *uint32, delta uint32) (new uint32)
AddUint32 атомарно добавляет delta к *addr и возвращает новое значение. Для вычитания знакового положительного константного значения c из x используйте AddUint32(&x, ^uint32(c-1)). В частности, для декремента x используйте AddUint32(&x, ^uint32(0)). Рассмотрите использование более удобного и менее подверженного ошибкам Uint32.Add вместо него.
func AddUint64
func AddUint64(addr *uint64, delta uint64) (new uint64)
AddUint64 атомарно добавляет delta к *addr и возвращает новое значение. Для вычитания знакового положительного константного значения c из x используйте AddUint64(&x, ^uint64(c-1)). В частности, для декремента x используйте AddUint64(&x, ^uint64(0)). Рассмотрите использование более удобного и менее подверженного ошибкам Uint64.Add вместо него (особенно если вы нацеливаетесь на 32-битные платформы; см. раздел об ошибках).
func AddUintptr
func AddUintptr(addr *uintptr, delta uintptr) (new uintptr)
AddUintptr атомарно добавляет delta к *addr и возвращает новое значение. Рассмотрите использование более удобного и менее подверженного ошибкам Uintptr.Add вместо него.
func AndInt32 1.23
func AndInt32(addr *int32, mask int32) (old int32)
AndInt32 атомарно выполняет побитовую операцию И над *addr с использованием битовой маски mask и возвращает старое значение. Рассмотрите использование более удобного и менее подверженного ошибкам Int32.And вместо него.
func AndInt64 1.23
func AndInt64(addr *int64, mask int64) (old int64)
AndInt64 атомарно выполняет побитовое И операцию над *addr с использованием предоставленной в качестве mask маски и возвращает старое значение. Рассмотрите использование более удобного и менее подверженного ошибкам Int64.And вместо этого.
func AndUint32 1.23
func AndUint32(addr *uint32, mask uint32) (old uint32)
AndUint32 атомарно выполняет побитовое И операцию над *addr с использованием предоставленной в качестве mask маски и возвращает старое значение. Рассмотрите использование более удобного и менее подверженного ошибкам Uint32.And вместо этого.
func AndUint64 1.23
func AndUint64(addr *uint64, mask uint64) (old uint64)
AndUint64 атомарно выполняет побитовое И операцию над *addr с использованием предоставленной в качестве mask маски и возвращает старое значение. Рассмотрите использование более удобного и менее подверженного ошибкам Uint64.And вместо этого.
func AndUintptr 1.23
func AndUintptr(addr *uintptr, mask uintptr) (old uintptr)
AndUintptr атомарно выполняет побитовое И операцию над *addr с использованием предоставленной в качестве mask маски и возвращает старое значение. Рассмотрите использование более удобного и менее подверженного ошибкам Uintptr.And вместо этого.
func CompareAndSwapInt32
func CompareAndSwapInt32(addr *int32, old, new int32) (swapped bool)
CompareAndSwapInt32 выполняет операцию сравнения и обмена для значения int32. Рассмотрите использование более удобного и менее подверженного ошибкам Int32.CompareAndSwap вместо этого.
func CompareAndSwapInt64
func CompareAndSwapInt64(addr *int64, old, new int64) (swapped bool)
CompareAndSwapInt64 выполняет операцию сравнения и обмена для значения int64. Рассмотрите использование более удобного и менее подверженного ошибкам Int64.CompareAndSwap вместо этого (особенно если вы нацеливаетесь на 32-битные платформы; см. раздел ошибок).
func CompareAndSwapPointer
func CompareAndSwapPointer(addr *unsafe.Pointer, old, new unsafe.Pointer) (swapped bool)
CompareAndSwapPointer выполняет операцию сравнения и обмена для значения unsafe.Pointer. Рассмотрите использование более удобного и менее подверженного ошибкам Pointer.CompareAndSwap вместо этого.
func CompareAndSwapUint32
func CompareAndSwapUint32(addr *uint32, old, new uint32) (swapped bool)
CompareAndSwapUint32 выполняет операцию сравнения и обмена для значения uint32. Рассмотрите использование более удобного и менее подверженного ошибкам Uint32.CompareAndSwap вместо этого.
func CompareAndSwapUint64
func CompareAndSwapUint64(addr *uint64, old, new uint64) (swapped bool)
CompareAndSwapUint64 выполняет операцию сравнения и обмена для значения uint64. Рассмотрите использование более удобного и менее подверженного ошибкам Uint64.CompareAndSwap вместо этого (особенно если вы нацеливаетесь на 32-битные платформы; см. раздел ошибок).
func CompareAndSwapUintptr
func CompareAndSwapUintptr(addr *uintptr, old, new uintptr) (swapped bool)
CompareAndSwapUintptr выполняет операцию сравнения и обмена для значения uintptr. Рассмотрите использование более удобного и менее подверженного ошибкам Uintptr.CompareAndSwap вместо этого.
func LoadInt32
func LoadInt32(addr *int32) (val int32)
LoadInt32 атомарно загружает *addr. Рассмотрите использование более удобного и менее подверженного ошибкам Int32.Load вместо этого.
func LoadInt64
func LoadInt64(addr *int64) (val int64)
LoadInt64 атомарно загружает *addr. Рассмотрите использование более удобного и менее подверженного ошибкам Int64.Load вместо этого (особенно если вы нацеливаетесь на 32-битные платформы; см. раздел ошибок).
func LoadPointer
func LoadPointer(addr *unsafe.Pointer) (val unsafe.Pointer)
LoadPointer атомарно загружает *addr. Рассмотрите использование более удобного и менее подверженного ошибкам Pointer.Load вместо этого.
func LoadUint32
func LoadUint32(addr *uint32) (val uint32)
LoadUint32 атомарно загружает *addr. Рассмотрите использование более удобного и менее подверженного ошибкам Uint32.Load вместо этого.
func LoadUint64
func LoadUint64(addr *uint64) (val uint64)
LoadUint64 атомарно загружает *addr. Рассмотрите использование более удобного и менее подверженного ошибкам Uint64.Load вместо этого (особенно если вы нацеливаетесь на 32-битные платформы; см. раздел ошибок).
func LoadUintptr
func LoadUintptr(addr *uintptr) (val uintptr)
LoadUintptr атомарно загружает *addr. Рассмотрите использование более удобного и менее подверженного ошибкам Uintptr.Load вместо этого.
func OrInt32 1.23
func OrInt32(addr *int32, mask int32) (old int32)
OrInt32 атомарно выполняет побитовое ИЛИ операцию над *addr с использованием предоставленной в качестве mask маски и возвращает старое значение. Рассмотрите использование более удобного и менее подверженного ошибкам Int32.Or вместо этого.
func OrInt64 1.23
func OrInt64(addr *int64, mask int64) (old int64)
OrInt64 атомарно выполняет побитовое ИЛИ операцию над *addr с использованием предоставленной в качестве mask маски и возвращает старое значение. Рассмотрите использование более удобного и менее подверженного ошибкам Int64.Or вместо этого.
func OrUint32 1.23
func OrUint32(addr *uint32, mask uint32) (old uint32)
OrUint32 атомарно выполняет побитовое ИЛИ операцию над *addr с использованием предоставленной в качестве mask маски и возвращает старое значение. Рассмотрите использование более удобного и менее подверженного ошибкам Uint32.Or вместо этого.
func OrUint64 1.23
func OrUint64(addr *uint64, mask uint64) (old uint64)
OrUint64 атомарно выполняет побитовое ИЛИ операцию над *addr с использованием предоставленной в качестве mask маски и возвращает старое значение. Рассмотрите использование более удобного и менее подверженного ошибкам Uint64.Or вместо этого.
func OrUintptr 1.23
func OrUintptr(addr *uintptr, mask uintptr) (old uintptr)
OrUintptr атомарно выполняет побитовое ИЛИ операцию над *addr с использованием предоставленной в качестве mask маски и возвращает старое значение. Рассмотрите использование более удобного и менее подверженного ошибкам Uintptr.Or вместо этого.
func StoreInt32
func StoreInt32(addr *int32, val int32)
StoreInt32 атомарно сохраняет val в *addr. Рассмотрите использование более удобного и менее подверженного ошибкам Int32.Store вместо этого.
func StoreInt64
func StoreInt64(addr *int64, val int64)
StoreInt64 атомарно сохраняет val в *addr. Рассмотрите использование более удобного и менее подверженного ошибкам Int64.Store вместо этого (особенно если вы нацеливаетесь на 32-битные платформы; см. раздел ошибок).
func StorePointer
func StorePointer(addr *unsafe.Pointer, val unsafe.Pointer)
StorePointer атомарно сохраняет val в *addr. Рассмотрите использование более удобного и менее подверженного ошибкам Pointer.Store вместо этого.
func StoreUint32
func StoreUint32(addr *uint32, val uint32)
StoreUint32 атомарно сохраняет val в *addr. Рассмотрите использование более удобного и менее подверженного ошибкам Uint32.Store вместо этого.
func StoreUint64
func StoreUint64(addr *uint64, val uint64)
StoreUint64 атомарно сохраняет val в *addr. Рассмотрите использование более удобного и менее подверженного ошибкам Uint64.Store вместо этого (особенно если вы нацеливаетесь на 32-битные платформы; см. раздел ошибок).
func StoreUintptr
func StoreUintptr(addr *uintptr, val uintptr)
StoreUintptr атомарно сохраняет val в *addr. Рассмотрите использование более удобного и менее подверженного ошибкам Uintptr.Store вместо этого.
func SwapInt32 1.2
func SwapInt32(addr *int32, new int32) (old int32)
SwapInt32 атомарно сохраняет new в *addr и возвращает предыдущее значение *addr. Рассмотрите использование более удобного и менее подверженного ошибкам Int32.Swap вместо этого.
func SwapInt64 1.2
func SwapInt64(addr *int64, new int64) (old int64)
SwapInt64 атомарно сохраняет new в *addr и возвращает предыдущее значение *addr. Рассмотрите использование более удобного и менее подверженного ошибкам Int64.Swap вместо этого (особенно если вы нацеливаетесь на 32-битные платформы; см. раздел ошибок).
func SwapPointer 1.2
func SwapPointer(addr *unsafe.Pointer, new unsafe.Pointer) (old unsafe.Pointer)
SwapPointer атомарно сохраняет new в *addr и возвращает предыдущее значение *addr. Рассмотрите использование более удобного и менее подверженного ошибкам Pointer.Swap вместо этого.
func SwapUint32 1.2
func SwapUint32(addr *uint32, new uint32) (old uint32)
SwapUint32 атомарно сохраняет new в *addr и возвращает предыдущее значение *addr. Рассмотрите использование более удобного и менее подверженного ошибкам Uint32.Swap вместо этого.
func SwapUint64 1.2
func SwapUint64(addr *uint64, new uint64) (old uint64)
SwapUint64 атомарно сохраняет new в *addr и возвращает предыдущее значение *addr. Рассмотрите использование более удобного и менее подверженного ошибкам Uint64.Swap вместо этого (особенно если вы нацеливаетесь на 32-битные платформы; см. раздел ошибок).
func SwapUintptr 1.2
func SwapUintptr(addr *uintptr, new uintptr) (old uintptr)
SwapUintptr атомарно сохраняет new в *addr и возвращает предыдущее значение *addr. Рассмотрите использование более удобного и менее подверженного ошибкам Uintptr.Swap вместо этого.
type Bool 1.19
Bool — атомное булево значение. Нулевое значение — false.
type Bool struct {
// contains filtered or unexported fields
}
func (*Bool) CompareAndSwap 1.19
func (x *Bool) CompareAndSwap(old, new bool) (swapped bool)
CompareAndSwap выполняет операцию сравнения и обмена для булевого значения x.
func (*Bool) Load 1.19
func (x *Bool) Load() bool
Load атомарно загружает и возвращает значение, хранящееся в x.
func (*Bool) Store 1.19
func (x *Bool) Store(val bool)
Store атомарно сохраняет val в x.
func (*Bool) Swap 1.19
func (x *Bool) Swap(new bool) (old bool)
Swap атомарно сохраняет new в x и возвращает предыдущее значение.
type Int32 1.19
Int32 — атомное значение int32. Нулевое значение — ноль.
type Int32 struct {
// contains filtered or unexported fields
}
func (*Int32) Add 1.19
func (x *Int32) Add(delta int32) (new int32)
Add атомарно прибавляет delta к x и возвращает новое значение.
func (*Int32) And 1.23
func (x *Int32) And(mask int32) (old int32)
And атомарно выполняет побитовое И операцию над x с использованием предоставленной в качестве mask маски и возвращает старое значение.
func (*Int32) CompareAndSwap 1.19
func (x *Int32) CompareAndSwap(old, new int32) (swapped bool)
CompareAndSwap выполняет операцию сравнения и обмена для x.
func (*Int32) Load 1.19
func (x *Int32) Load() int32
Load атомарно загружает и возвращает значение, хранящееся в x.
func (*Int32) Or 1.23
func (x *Int32) Or(mask int32) (old int32)
Или атомарно выполняет побитовое ИЛИ-операцию над x, используя предоставленную маску, и возвращает старое значение.
func (*Int32) Store 1.19
func (x *Int32) Store(val int32)
Атомарно сохраняет val в x.
func (*Int32) Swap 1.19
func (x *Int32) Swap(new int32) (old int32)
Атомарно сохраняет new в x и возвращает предыдущее значение.
type Int64 1.19
Int64 — это атомное целое число со знаком 64 бита. Нулевое значение — ноль.
type Int64 struct {
// contains filtered or unexported fields
}
func (*Int64) Add 1.19
func (x *Int64) Add(delta int64) (new int64)
Атомарно прибавляет delta к x и возвращает новое значение.
func (*Int64) And 1.23
func (x *Int64) And(mask int64) (old int64)
Атомарно выполняет побитовую операцию И над x, используя предоставленную маску, и возвращает старое значение.
func (*Int64) CompareAndSwap 1.19
func (x *Int64) CompareAndSwap(old, new int64) (swapped bool)
Выполняет операцию сравнения и обмена для x.
func (*Int64) Load 1.19
func (x *Int64) Load() int64
Атомарно загружает и возвращает значение, сохранённое в x.
func (*Int64) Or 1.23
func (x *Int64) Or(mask int64) (old int64)
Атомарно выполняет побитовую операцию ИЛИ над x, используя предоставленную маску, и возвращает старое значение.
func (*Int64) Store 1.19
func (x *Int64) Store(val int64)
Атомарно сохраняет val в x.
func (*Int64) Swap 1.19
func (x *Int64) Swap(new int64) (old int64)
Атомарно сохраняет new в x и возвращает предыдущее значение.
type Pointer
Pointer — это атомный указатель типа *T. Нулевое значение — nil *T.
type Pointer[T any] struct {
// contains filtered or unexported fields
}
func (*Pointer[T]) CompareAndSwap
func (x *Pointer[T]) CompareAndSwap(old, new *T) (swapped bool)
Выполняет операцию сравнения и обмена для x.
func (*Pointer[T]) Load
func (x *Pointer[T]) Load() *T
Атомарно загружает и возвращает значение, сохранённое в x.
func (*Pointer[T]) Store
func (x *Pointer[T]) Store(val *T)
Атомарно сохраняет val в x.
func (*Pointer[T]) Swap
func (x *Pointer[T]) Swap(new *T) (old *T)
Атомарно сохраняет new в x и возвращает предыдущее значение.
type Uint32 1.19
Uint32 — это атомное целое число без знака 32 бита. Нулевое значение — ноль.
type Uint32 struct {
// contains filtered or unexported fields
}
func (*Uint32) Add 1.19
func (x *Uint32) Add(delta uint32) (new uint32)
Атомарно прибавляет delta к x и возвращает новое значение.
func (*Uint32) And 1.23
func (x *Uint32) And(mask uint32) (old uint32)
Атомарно выполняет побитовую операцию И над x, используя предоставленную маску, и возвращает старое значение.
func (*Uint32) CompareAndSwap 1.19
func (x *Uint32) CompareAndSwap(old, new uint32) (swapped bool)
Выполняет операцию сравнения и обмена для x.
func (*Uint32) Load 1.19
func (x *Uint32) Load() uint32
Атомарно загружает и возвращает значение, сохранённое в x.
func (*Uint32) Or 1.23
func (x *Uint32) Or(mask uint32) (old uint32)
Атомарно выполняет побитовую операцию ИЛИ над x, используя предоставленную маску, и возвращает старое значение.
func (*Uint32) Store 1.19
func (x *Uint32) Store(val uint32)
Атомарно сохраняет val в x.
func (*Uint32) Swap 1.19
func (x *Uint32) Swap(new uint32) (old uint32)
Атомарно сохраняет new в x и возвращает предыдущее значение.
type Uint64 1.19
Uint64 — это атомное целое число без знака 64 бита. Нулевое значение — ноль.
type Uint64 struct {
// contains filtered or unexported fields
}
func (*Uint64) Add 1.19
func (x *Uint64) Add(delta uint64) (new uint64)
Атомарно прибавляет delta к x и возвращает новое значение.
func (*Uint64) And 1.23
func (x *Uint64) And(mask uint64) (old uint64)
Атомарно выполняет побитовую операцию И над x, используя предоставленную маску, и возвращает старое значение.
func (*Uint64) CompareAndSwap 1.19
func (x *Uint64) CompareAndSwap(old, new uint64) (swapped bool)
Выполняет операцию сравнения и обмена для x.
func (*Uint64) Load 1.19
func (x *Uint64) Load() uint64
Атомарно загружает и возвращает значение, сохранённое в x.
func (*Uint64) Or 1.23
func (x *Uint64) Or(mask uint64) (old uint64)
Атомарно выполняет побитовую операцию ИЛИ над x, используя предоставленную маску, и возвращает старое значение.
func (*Uint64) Store 1.19
func (x *Uint64) Store(val uint64)
Атомарно сохраняет val в x.
func (*Uint64) Swap 1.19
func (x *Uint64) Swap(new uint64) (old uint64)
Атомарно сохраняет new в x и возвращает предыдущее значение.
type Uintptr 1.19
Uintptr — это атомный указатель без знака. Нулевое значение — ноль.
type Uintptr struct {
// contains filtered or unexported fields
}
func (*Uintptr) Add 1.19
func (x *Uintptr) Add(delta uintptr) (new uintptr)
Атомарно прибавляет delta к x и возвращает новое значение.
func (*Uintptr) And 1.23
func (x *Uintptr) And(mask uintptr) (old uintptr)
Атомарно выполняет побитовую операцию И над x, используя предоставленную маску, и возвращает старое значение.
func (*Uintptr) CompareAndSwap 1.19
func (x *Uintptr) CompareAndSwap(old, new uintptr) (swapped bool)
Выполняет операцию сравнения и обмена для x.
func (*Uintptr) Load 1.19
func (x *Uintptr) Load() uintptr
Атомарно загружает и возвращает значение, сохранённое в x.
func (*Uintptr) Or 1.23
func (x *Uintptr) Or(mask uintptr) (old uintptr)
Атомарно выполняет побитовую операцию ИЛИ над x, используя предоставленную маску, и возвращает обновлённое значение после операции ИЛИ.
func (*Uintptr) Store 1.19
func (x *Uintptr) Store(val uintptr)
Атомарно сохраняет val в x.
func (*Uintptr) Swap 1.19
func (x *Uintptr) Swap(new uintptr) (old uintptr)
Атомарно сохраняет new в x и возвращает предыдущее значение.
type Value 1.4
Value обеспечивает атомную загрузку и сохранение значения с постоянным типом. Нулевое значение для Value возвращает nil из Value.Load. После вызова Value.Store, Value не следует копировать.
Value не следует копировать после первого использования.
type Value struct {
// contains filtered or unexported fields
}
Пример (Конфигурация)
Следующий пример демонстрирует использование Value для периодических обновлений конфигурации программы и распространения изменений рабочим горутинам.
Код:
var config atomic.Value // holds current server configuration
// Create initial config value and store into config.
config.Store(loadConfig())
go func() {
// Reload config every 10 seconds
// and update config value with the new version.
for {
time.Sleep(10 * time.Second)
config.Store(loadConfig())
}
}()
// Create worker goroutines that handle incoming requests
// using the latest config value.
for i := 0; i < 10; i++ {
go func() {
for r := range requests() {
c := config.Load()
// Handle request r using config c.
_, _ = r, c
}
}()
}
Пример (Часто читаемый)
Следующий пример показывает, как поддерживать масштабируемую часто читаемую, но редко обновляемую структуру данных, используя идею копирования при изменении.
Код:
type Map map[string]string
var m atomic.Value
m.Store(make(Map))
var mu sync.Mutex // used only by writers
// read function can be used to read the data without further synchronization
read := func(key string) (val string) {
m1 := m.Load().(Map)
return m1[key]
}
// insert function can be used to update the data without further synchronization
insert := func(key, val string) {
mu.Lock() // synchronize with other potential writers
defer mu.Unlock()
m1 := m.Load().(Map) // load current value of the data structure
m2 := make(Map) // create a new value
for k, v := range m1 {
m2[k] = v // copy all data from the current object to the new one
}
m2[key] = val // do the update that we need
m.Store(m2) // atomically replace the current object with the new one
// At this point all new readers start working with the new version.
// The old version will be garbage collected once the existing readers
// (if any) are done with it.
}
_, _ = read, insert
func (*Value) CompareAndSwap 1.17
func (v *Value) CompareAndSwap(old, new any) (swapped bool)
CompareAndSwap выполняет операцию сравнения и обмена для Value.
Все вызовы CompareAndSwap для данного Value должны использовать значения одного и того же конкретного типа. CompareAndSwap несовместимого типа вызывает панику, как и CompareAndSwap(old, nil).
func (*Value) Load 1.4
func (v *Value) Load() (val any)
Load возвращает значение, установленное последним Store. Возвращает nil, если для данного Value не было вызова Store.
func (*Value) Store 1.4
func (v *Value) Store(val any)
Store устанавливает значение Value v в val. Все вызовы Store для данного Value должны использовать значения одного и того же конкретного типа. Store несовместимого типа вызывает панику, как и Store(nil).
func (*Value) Swap 1.17
func (v *Value) Swap(new any) (old any)
Swap сохраняет new в Value и возвращает предыдущее значение. Возвращает nil, если Value пуст.
Все вызовы Swap для данного Value должны использовать значения одного и того же конкретного типа. Swap несовместимого типа вызывает панику, как и Swap(nil).
Ошибки
- ☞
На 386, 64-битные функции используют инструкции, недоступные до Pentium MMX.
На не-Linux ARM, 64-битные функции используют инструкции, недоступные до ARMv6k core.
На ARM, 386 и 32-битном MIPS, ответственность за обеспечение 64-битного выравнивания 64-битовых слов, обращённых атомарно через примитивные атомные функции (типы Int64 и Uint64 автоматически выровнены), лежит на вызывающей стороне. Первый байт в выделенной структуре, массиве или срезе, в глобальной переменной или в локальной переменной (потому что тема всех атомных операций будет уходить в кучу) можно считать 64-битным выровненным.
© Google, Inc.
Licensed under the Creative Commons Attribution License 3.0.
http://golang.org/pkg/sync/atomic/