atomic
12 分钟阅读
atomic
https://pkg.go.dev/sync/atomic@go1.20.1
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++的顺序一致原子和Java的易失性变量相同的语义。
常量
This section is empty.
变量
This section is empty.
函数
func AddInt32
|
|
AddInt32函数原子地将delta添加到*addr
,并返回新值。考虑使用更符合人体工程学和更不容易出错的Int32.Add代替。
func AddInt64
|
|
AddInt64函数原子地将delta添加到*addr
,并返回新值。如果您的目标是32位平台,请考虑使用更符合人体工程学和更不容易出错的Int64.Add代替(请参见错误部分)。
func AddUint32
|
|
AddUint32函数原子地将delta添加到*addr
,并返回新值。要从x减去已知正常数值c,请执行AddUint32(&x,^uint32(c-1))。特别地,要将x减少1,请执行AddUint32(&x,^uint32(0))。考虑使用更符合人体工程学和更不容易出错的Uint32.Add代替。
func AddUint64
|
|
AddUint64函数原子地将delta添加到*addr
,并返回新值。要从x减去已知正常数值c,请执行AddUint64(&x,^uint64(c-1))。特别地,要将x减少1,请执行AddUint64(&x,^uint64(0))。如果您的目标是32位平台,请考虑使用更符合人体工程学和更不容易出错的Uint64.Add代替(请参见错误部分)。
func AddUintptr
|
|
AddUintptr函数原子地将delta添加到*addr
,并返回新值。考虑使用更符合人体工程学和更不容易出错的Uintptr.Add代替。
func CompareAndSwapInt32
|
|
CompareAndSwapInt32函数执行 int32 值的比较并交换操作。建议使用更符合人体工程学和更少容易出错的 Int32.CompareAndSwap。
func CompareAndSwapInt64
|
|
CompareAndSwapInt64函数执行 int64 值的比较并交换操作。建议使用更符合人体工程学和更少容易出错的 Int64.CompareAndSwap (特别是针对 32 位平台;参见错误部分)。
func CompareAndSwapPointer
|
|
CompareAndSwapPointer函数执行 unsafe.Pointer 值的比较并交换操作。建议使用更符合人体工程学和更少容易出错的 Pointer.CompareAndSwap。
func CompareAndSwapUint32
|
|
CompareAndSwapUint32函数执行 uint32 值的比较并交换操作。建议使用更符合人体工程学和更少容易出错的 Uint32.CompareAndSwap。
func CompareAndSwapUint64
|
|
CompareAndSwapUint64函数执行 uint64 值的比较并交换操作。建议使用更符合人体工程学和更少容易出错的 Uint64.CompareAndSwap (特别是针对 32 位平台;参见错误部分)。
func CompareAndSwapUintptr
|
|
CompareAndSwapUintptr函数执行 uintptr 值的比较并交换操作。建议使用更符合人体工程学和更少容易出错的 Uintptr.CompareAndSwap。
func LoadInt32
|
|
LoadInt32函数原子地加载 *addr
。考虑使用更符合人体工程学且不易出错的 Int32.Load。
func LoadInt64
|
|
LoadInt64函数原子地加载 *addr
。考虑使用更符合人体工程学且不易出错的 Int64.Load(特别是如果您的目标是32位平台;请参见错误部分)。
func LoadPointer
|
|
LoadPointer函数原子地加载 *addr
。考虑使用更符合人体工程学且不易出错的 Pointer.Load。
func LoadUint32
|
|
LoadUint32函数原子地加载 *addr
。考虑使用更符合人体工程学且不易出错的 Uint32.Load。
func LoadUint64
|
|
LoadUint64函数原子地加载 *addr
。考虑使用更符合人体工程学且不易出错的 Uint64.Load(特别是如果您的目标是32位平台;请参见错误部分)。
func LoadUintptr
|
|
LoadUintptr函数原子地加载 *addr
。考虑使用更符合人体工程学且不易出错的 Uintptr.Load。
func StoreInt32
|
|
StoreInt32函数原子地将 val 存储到 *addr
。考虑使用更符合人体工程学且不易出错的 Int32.Store。
func StoreInt64
|
|
StoreInt64函数原子地将 val 存储到 *addr
。考虑使用更符合人体工程学且不易出错的 Int64.Store(特别是如果您的目标是32位平台;请参见错误部分)。
func StorePointer
|
|
StorePointer函数原子地将 val 存储到 *addr
。考虑使用更符合人体工程学且不易出错的 Pointer.Store。
func StoreUint32
|
|
StoreUint32函数原子性地将val存储到*addr
。考虑使用更符合人体工程学且更少出错的Uint32.Store。
func StoreUint64
|
|
StoreUint64函数原子性地将val存储到*addr
。考虑使用更符合人体工程学且更少出错的Uint64.Store(特别是针对32位平台,参见bugs一节)。
func StoreUintptr
|
|
StoreUintptr函数原子性地将val存储到*addr
。考虑使用更符合人体工程学且更少出错的Uintptr.Store。
func SwapInt32 <- go1.2
|
|
SwapInt32函数原子性地将new存储到*addr
并返回先前的*addr
值。考虑使用更符合人体工程学且更少出错的Int32.Swap。
func SwapInt64 <- go1.2
|
|
SwapInt64函数原子性地将new存储到*addr
并返回先前的*addr
值。考虑使用更符合人体工程学且更少出错的Int64.Swap(特别是针对32位平台,参见bugs一节)。
func SwapPointer <- go1.2
|
|
SwapPointer函数原子性地将new存储到*addr
并返回先前的*addr
值。考虑使用更符合人体工程学且更少出错的Pointer.Swap。
func SwapUint32 <- go1.2
|
|
SwapUint32函数原子性地将new存储到*addr
并返回先前的*addr
值。考虑使用更符合人体工程学且更少出错的Uint32.Swap。
func SwapUint64 <- go1.2
|
|
SwapUint64函数原子性地将new存储到*addr
并返回先前的*addr
值。考虑使用更符合人体工程学且更少出错的Uint64.Swap(特别是针对32位平台,参见bugs一节)。
func SwapUintptr <- go1.2
|
|
SwapUintptr函数原子性地将new存储到*addr
并返回先前的*addr
值。考虑使用更符合人体工程学且更少出错的Uintptr.Swap。
类型
type Bool <- go1.19
|
|
Bool结构体是一个原子布尔值。 零值为false。
(*Bool) CompareAndSwap <- go1.19
|
|
CompareAndSwap方法执行布尔值x的比较和交换操作。
(*Bool) Load <- go1.19
|
|
Load方法以原子方式加载并返回存储在x中的值。
(*Bool) Store <- go1.19
|
|
Store方法原子地将val存储到x中。
(*Bool) Swap <- go1.19
|
|
Swap方法以原子方式将new存储到x中并返回先前的值。
type Int32 <- go1.19
|
|
Int32方法是一个原子int32。 零值为零。
(*Int32) Add <- go1.19
|
|
Add方法原子地将delta添加到x并返回新值。
(*Int32) CompareAndSwap <- go1.19
|
|
CompareAndSwap方法执行x的比较和交换操作。
(*Int32) Load <- go1.19
|
|
Load方法原子地加载并返回存储在x中的值。
(*Int32) Store <- go1.19
|
|
Store方法原子地将val存储到x中。
(*Int32) Swap <- go1.19
|
|
Swap方法原子地将new存储到x中并返回先前的值。
type Int64 <- go1.19
|
|
Int64方法是原子int64。零值为零。
(*Int64) Add <- go1.19
|
|
Add方法原子地将delta添加到x并返回新值。
(*Int64) CompareAndSwap <- go1.19
|
|
CompareAndSwap方法执行x的比较并交换操作。
(*Int64) Load <- go1.19
|
|
Load方法原子地加载并返回存储在x中的值。
(*Int64) Store <- go1.19
|
|
Store方法原子地将val存储到x中。
(*Int64) Swap <- go1.19
|
|
Swap方法原子地将new存储到x中并返回先前的值。
type Pointer <- go1.19
|
|
Pointer 是一个类型为 *T 的原子指针。零值是 nil 的 *T。
(*Pointer[T]) CompareAndSwap <- go1.19
|
|
CompareAndSwap方法执行 x 的比较并交换操作。
(*Pointer[T]) Load <- go1.19
|
|
Load方法原子地加载并返回存储在 x 中的值。
(*Pointer[T]) Store <- go1.19
|
|
Store方法原子地将 val 存储到 x 中。
(*Pointer[T]) Swap <- go1.19
|
|
Swap方法原子地将 new 存储到 x 中,并返回先前的值。
type Uint32 <- go1.19
|
|
Uint32方法是一个原子 uint32。零值是零。
(*Uint32) Add <- go1.19
|
|
Add方法原子地将 delta 添加到 x 并返回新值。
(*Uint32) CompareAndSwap <- go1.19
|
|
CompareAndSwap方法执行 x 的比较并交换操作。
(*Uint32) Load <- go1.19
|
|
Load方法原子地加载并返回存储在x中的值。
(*Uint32) Store <- go1.19
|
|
Store方法原子地将val存储到x中。
(*Uint32) Swap <- go1.19
|
|
Swap方法原子地将new存储到x中并返回先前的值。
type Uint64 <- go1.19
|
|
Uint64方法是一个原子性的uint64类型。零值为零。
(*Uint64) Add <- go1.19
|
|
Add方法原子性地将delta添加到x中并返回新值。
(*Uint64) CompareAndSwap <- go1.19
|
|
CompareAndSwap方法在x上执行比较并交换操作。
(*Uint64) Load <- go1.19
|
|
Load方法原子地加载并返回存储在x中的值。
(*Uint64) Store <- go1.19
|
|
Store方法原子地将val存储到x中。
(*Uint64) Swap <- go1.19
|
|
Swap方法原子地将new存储到x中并返回先前的值。
type Uintptr <- go1.19
|
|
Uintptr是一个原子的uintptr类型。零值为零。
(*Uintptr) Add <- go1.19
|
|
Add方法原子地将delta添加到x并返回新值。
(*Uintptr) CompareAndSwap <- go1.19
|
|
CompareAndSwap方法执行x的比较和交换操作。
(*Uintptr) Load <- go1.19
|
|
Load方法以原子方式加载并返回存储在x中的值。
(*Uintptr) Store <- go1.19
|
|
Store方法以原子方式将val存储到x中。
(*Uintptr) Swap <- go1.19
|
|
Swap方法以原子方式将new存储到x中并返回先前的值。
type Value <- go1.4
|
|
Value类型提供了一个一致类型值的原子加载和存储。Value类型的零值从Load返回nil。一旦调用了Store,就不能再复制Value。
使用后不能再复制Value。
Example (Config)
The following example shows how to use Value for periodic program config updates and propagation of the changes to worker goroutines.
|
|
Example (ReadMostly)
The following example shows how to maintain a scalable frequently read, but infrequently updated data structure using copy-on-write idiom.
|
|
(*Value) CompareAndSwap <- go1.17
|
|
CompareAndSwap方法为Value执行比较和交换操作。
所有对给定Value的CompareAndSwap调用必须使用相同具体类型的值。类型不一致的CompareAndSwap会导致panic,CompareAndSwap(old, nil)也是如此。
(*Value) Load <- go1.4
|
|
Load方法返回最近一次Store设置的值。如果没有为此Value调用Store,则返回nil。
(*Value) Store <- go1.4
|
|
Store方法将Value v的值设置为val。所有对给定Value的Store调用必须使用相同具体类型的值。类型不一致的Store会导致panic,Store(nil)也是如此。
(*Value) Swap <- go1.17
|
|
Swap方法操作将new值存储到Value中,并返回旧值。如果Value为空,则返回nil。
对于同一个 Value,所有 Swap方法的调用必须使用相同的具体类型的值。如果使用不一致的类型进行 Swap方法,会导致 panic,就像 Swap(nil) 一样。
Notes
Bugs
在386上,64位函数使用Pentium MMX之前不可用的指令。
在非Linux ARM上,64位函数使用ARMv6k核心之前不可用的指令。
在ARM,386和32位MIPS上,通过原子函数访问64位字(类型Int64和Uint64自动对齐)的调用方有责任安排64位对齐。可以依靠分配的结构体,数组或切片中的第一个字,全局变量中的第一个字或局部变量中的第一个字(因为所有原子操作的主题都将逃逸到堆中)为64位对齐。