原子操作 | sync/atomic

打包atomic

  • import "sync/atomic"

  • 概观

  • 索引

  • 示例

概观

Package atomic 提供了用于实现同步算法的低级原子内存原语。

这些功能需要非常小心才能正确使用。除特殊的低级别应用程序外,同步更适合使用频道或同步软件包的功能。通过沟通共享内存; 不要通过共享内存进行通信。

由 SwapT 函数实现的交换操作是以下原子等值:

old = *addr *addr = new return old

由 CompareAndSwapT 函数实现的比较和交换操作与以下原子等价:

if *addr == old { *addr = new return true } return false

由 Add T函数实现的 add 操作与以下操作相当:

*addr += delta return *addr

由 LoadT 和 StoreT 函数实现的加载和存储操作是 "return *addr" and "*addr = val" 的原子等价物。

索引

  • func AddInt32(addr *int32, delta int32) (new int32)

  • func AddInt64(addr *int64, delta int64) (new int64)

  • func AddUint32(addr *uint32, delta uint32) (new uint32)

  • func AddUint64(addr *uint64, delta uint64) (new uint64)

  • func AddUintptr(addr *uintptr, delta uintptr) (new uintptr)

  • func CompareAndSwapInt32(addr *int32, old, new int32) (swapped bool)

  • func CompareAndSwapInt64(addr *int64, old, new int64) (swapped bool)

  • func CompareAndSwapPointer(addr *unsafe.Pointer, old, new unsafe.Pointer) (swapped bool)

  • func CompareAndSwapUint32(addr *uint32, old, new uint32) (swapped bool)

  • func CompareAndSwapUint64(addr *uint64, old, new uint64) (swapped bool)

  • func CompareAndSwapUintptr(addr *uintptr, old, new uintptr) (swapped bool)

  • func LoadInt32(addr *int32) (val int32)

  • func LoadInt64(addr *int64) (val int64)

  • func LoadPointer(addr *unsafe.Pointer) (val unsafe.Pointer)

  • func LoadUint32(addr *uint32) (val uint32)

  • func LoadUint64(addr *uint64) (val uint64)

  • func LoadUintptr(addr *uintptr) (val uintptr)

  • func StoreInt32(addr *int32, val int32)

  • func StoreInt64(addr *int64, val int64)

  • func StorePointer(addr *unsafe.Pointer, val unsafe.Pointer)

  • func StoreUint32(addr *uint32, val uint32)

  • func StoreUint64(addr *uint64, val uint64)

  • func StoreUintptr(addr *uintptr, val uintptr)

  • func SwapInt32(addr *int32, new int32) (old int32)

  • func SwapInt64(addr *int64, new int64) (old int64)

  • func SwapPointer(addr *unsafe.Pointer, new unsafe.Pointer) (old unsafe.Pointer)

  • func SwapUint32(addr *uint32, new uint32) (old uint32)

  • func SwapUint64(addr *uint64, new uint64) (old uint64)

  • func SwapUintptr(addr *uintptr, new uintptr) (old uintptr)

  • type Value

  • func (v *Value) Load() (x interface{})

  • func (v *Value) Store(x interface{})

  • 错误

示例

Value (Config) Value (ReadMostly)

打包文件

doc.go value.go

func AddInt32Source

func AddInt32(addr *int32, delta int32) (new int32)

AddInt32 自动地将增量添加到 * addr 并返回新值。

func AddInt64Source

func AddInt64(addr *int64, delta int64) (new int64)

AddInt64 自动地将增量添加到 * addr 并返回新值。

func AddUint32Source

func AddUint32(addr *uint32, delta uint32) (new uint32)

AddUint32 自动地将增量添加到 * addr 并返回新值。要从 x 中减去一个带符号的正常数值 c ,请执行 AddUint32(&x, ^uint32(c-1))。特别是,要减少 x ,请执行 AddUint32(&x, ^uint32(0)) 。

func AddUint64Source

func AddUint64(addr *uint64, delta uint64) (new uint64)

AddUint64 自动地将增量添加到 * addr 并返回新值。要从 x 中减去一个带符号的正常数值 c ,请执行 AddUint64(&x, ^uint64(c-1))。特别是,要减少 x ,请执行 AddUint64(&x, ^uint64(0)) 。

func AddUintptrSource

func AddUintptr(addr *uintptr, delta uintptr) (new uintptr)

AddUintptr 自动向 delta addr 添加 delta 并返回新值。

func CompareAndSwapInt32Source

func CompareAndSwapInt32(addr *int32, old, new int32) (swapped bool)

CompareAndSwapInt32 为 int32 值执行比较和交换操作。

func CompareAndSwapInt64Source

func CompareAndSwapInt64(addr *int64, old, new int64) (swapped bool)

CompareAndSwapInt64 为 int64 值执行比较和交换操作。

func CompareAndSwapPointerSource

func CompareAndSwapPointer(addr *unsafe.Pointer, old, new unsafe.Pointer) (swapped bool)

CompareAndSwapPointer 对不安全的指针值执行比较和交换操作。

func CompareAndSwapUint32Source

func CompareAndSwapUint32(addr *uint32, old, new uint32) (swapped bool)

CompareAndSwapUint32 为 uint32 值执行比较和交换操作。

func CompareAndSwapUint64Source

func CompareAndSwapUint64(addr *uint64, old, new uint64) (swapped bool)

CompareAndSwapUint64 为 uint64 值执行比较和交换操作。

func CompareAndSwapUintptrSource

func CompareAndSwapUintptr(addr *uintptr, old, new uintptr) (swapped bool)

CompareAndSwapUintptr 为 uintptr 值执行比较和交换操作。

func LoadInt32Source

func LoadInt32(addr *int32) (val int32)

LoadInt32 自动加载 * addr 。

func LoadInt64Source

func LoadInt64(addr *int64) (val int64)

LoadInt64 自动加载 * addr 。

func LoadPointerSource

func LoadPointer(addr *unsafe.Pointer) (val unsafe.Pointer)

LoadPointer atomically loads *addr.

func LoadUint32Source

func LoadUint32(addr *uint32) (val uint32)

LoadUint32 自动加载 * addr 。

func LoadUint64Source

func LoadUint64(addr *uint64) (val uint64)

LoadUint64 自动地加载 * addr 。

func LoadUintptrSource

func LoadUintptr(addr *uintptr) (val uintptr)

LoadUintptr 自动加载 * addr 。

func StoreInt32Source

func StoreInt32(addr *int32, val int32)

StoreInt32 自动地将 val 存储到 * addr 中。

func StoreInt64Source

func StoreInt64(addr *int64, val int64)

StoreInt64 自动地将 val 存储到 * addr 中。

func StorePointerSource

func StorePointer(addr *unsafe.Pointer, val unsafe.Pointer)

StorePointer 自动地将 val 存储到 * addr 中。

func StoreUint32Source

func StoreUint32(addr *uint32, val uint32)

StoreUint32 自动地将 val 存储到 * addr 中。

func StoreUint64Source

func StoreUint64(addr *uint64, val uint64)

StoreUint64 自动地将 val 存储到 * addr 中。

func StoreUintptrSource

func StoreUintptr(addr *uintptr, val uintptr)

StoreUintptr 自动将 val 存储到 * addr 中。

func SwapInt32Source

func SwapInt32(addr *int32, new int32) (old int32)

SwapInt32 将自动地新成员存储到 * addr 并返回以前的 * addr 值。

func SwapInt64Source

func SwapInt64(addr *int64, new int64) (old int64)

SwapInt64 自动地将新的值存储到 * addr 并返回前一个 * addr 值。

func SwapPointerSource

func SwapPointer(addr *unsafe.Pointer, new unsafe.Pointer) (old unsafe.Pointer)

SwapPointer 自动地将新的值存储到 * addr 并返回以前的 * addr 值。

func SwapUint32Source

func SwapUint32(addr *uint32, new uint32) (old uint32)

SwapUint32 自动地将新的值存储到 * addr 并返回前一个 * addr 值。

func SwapUint64Source

func SwapUint64(addr *uint64, new uint64) (old uint64)

SwapUint64 自动地将新的值存储到 * addr 中,并返回以前的 * addr 值。

func SwapUintptrSource

func SwapUintptr(addr *uintptr, new uintptr) (old uintptr)

SwapUintptr 自动地将新值存储到 * addr 中,并返回前一个 * addr 值。

type ValueSource

值提供了一个自动加载和一个一致的类型值的存储。Value 的零值从 Load 返回 nil 。一旦 Store 被调用,Value 不能被复制。

首次使用后不得复制 Value 。

type Value struct { // contains filtered or unexported fields }

示例(配置)

以下示例显示如何使用 Value 进行周期性程序配置更新以及将更改传播到工作程序。

编码:

var config 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 } }() }

示例(ReadMostly)

以下示例说明如何使用写入时复制习惯用法维护可扩展的经常读取但不经常更新的数据结构。

编码:

type Map map[string]string var m 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) LoadSource

func (v *Value) Load() (x interface{})

Load 返回最近的存储设置的值。如果此值没有存储调用,则返回 nil 。

func (*Value) StoreSource

func (v *Value) Store(x interface{})

Store 将 Value 的值设置为 x 。对于给定值的所有对 Store的调用都必须使用相同具体类型的值。存储不一致的类型恐慌,就像 Store(nil) 一样。

错误

  • 在x86-32上,64位函数使用 Pentium MMX 之前不可用的指令。

在非 Linux ARM 上,64位函数使用 ARMv6k 内核之前不可用的指令。

在 ARM 和 x86-32 上,调用者都有责任安排自动访问64位字的64位对齐方式。变量或分配的结构,数组或片中的第一个字可以依赖于64位对齐。