Atomic
Overview
包atomic提供了底层原子atomic memory原语,用于实现同步算法. 这些函数要求格外的小心才能正确使用.除了特别的底层应用,同步最好使用通道或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”
func AddInt32(data *int32, delta int32) (new int32)
将data原子性的增加delta,并返回其值func AddInt64(data *int64, delta int64) (new int64)
将data原子性的增加delta,并返回其值func AddUint32(data *uint32, delta uint32) (new uint32)
将data原子性的增加delta,并返回其值func AddUint64(data *uint64, delta uint64) (new uint64)
将data原子性的增加delta,并返回其值func AddUintptr(addr *uintptr, delta uintptr) (new uintptr)
将addr原子性的增加delta,并返回其值func CompareAndSwapInt32(addr *int, old, new int32) (swaped bool)
如果值和old相同,则将addr和new原子性的交换,并返回是否交换func CompareAndSwapInt64(addr *int64, old, new int64) (swapped bool)
如果值和old相同,则将add和new原子性的交换,并返回是否交换func CompareAndSwapUint32(addr *uint32, old, new uint32) (swapped bool)
如果值和old相同,则将add和new原子性的交换,并返回是否交换func CompareAndSwapUint64(addr *uint64, old, new uint64) (swapped bool)
如果值和old相同,则将add和new原子性的交换,并返回是否交换func CompareAndSwapUintptr(addr *uintptr, old, new uintptr) (swapped bool)
如果值和old相同,则将add和new原子性的交换,并返回是否交换func CompareAndSwapPointer(addr *unsafe.Pointer, old, new unsafe.Pointer) (swapped bool)
如果值和old相同,则将add和new原子性的交换,并返回是否交换func LoadInt32(addr *int32) (val int32)
加载addr数据func LoadInt64(addr *int64) (val int64)
加载addr数据func LoadUint32(addr *uint32) (val uint32)
加载addr数据func LoadUint64(addr *uint64) (val uint64)
加载addr数据func LoadPointer(addr *unsafe.Pointer) (val unsafe.Pointer)
加载addr数据func LoadUintptr(addr *uintptr) (val uintptr)
加载addr数据func StoreInt32(addr *int32, val int32)
原子性的将val存储到addrfunc StoreInt64(addr *int64, val int64)
原子性的将val存储到addrfunc StoreUint32(addr *uint32, val uint32)
原子性的将val存储到addrfunc StoreUint64(addr *uint64, val uint64)
func StoreUintptr(addr *uint64, val uintptr)
StoreUintptr原子性的存储val到addrfunc SwapInt32(addr *int32, new int32) (old int32)
SwapInt32原子性的存储new到*addr,并返回原来的*addrfunc SwapInt64(addr *int64, new int64) (old int64)
SwapInt64原子性的存储new到*addr,并返回原来的*addrfunc SwapUint32(addr *uint32, new uint32) (old uint32)
SwapUint32原子性的存储new到*addr,并返回原来的*addrfunc SwapUint64(addr *uint64, new uint64) (old uint64)
SwapUint64原子性的存储new到*addr,并返回原来的*addrfunc SwapUintptr(addr *uintptr, new uintptr) (old uintptr)
SwapUintptr原子性的存储new到*addr,并返回原来的*addrfunc SwapPointer(addr *unsafe.Pointer, new unsafe.Pointer) (old unsafe.Pointer)
SwapPointer原子性的存储new到*addr,并返回原来的*addrtype Value
type Value struct {
// contains filtered or unexported fields
}
Value提供了原子性的加载和存储的一致性类型,Value的零值从Value返回nil,一旦Store调用,Value将不能被复制.
Value使用后必须不能被复制
func (v *Value) Load() (x interface{})
Load返回最近Store设置的值,如果没有调用过Store返回nilfunc (v *Value) Store(x interface{})
设置Value的值为x,所有调用Store给出的值必须是固定的类型,设置不一致的类型将会panic,比如Store(nil)Example
package main
import (
"sync"
"fmt"
)
func main() {
var done sync.WaitGroup
done.Add(2)
firstPipe := 0
secondPipe := 0
go func() {
for i := 0; i < 50; i++ {
firstPipe++
}
done.Done()
}()
go func() {
for i := 0; i < 200; i++ {
secondPipe++
}
done.Done()
}()
done.Wait()
fmt.Println("total: ", (firstPipe + secondPipe))
}
Example
package main
import (
"sync"
"sync/atomic"
"fmt"
)
func main() {
var counter int32 = 0
// for add 2
times := 100000
var done sync.WaitGroup
done.Add(2)
go func() {
for i := 0; i < times; i++ {
atomic.AddInt32(&counter, 2)
}
defer done.Done()
}()
// for sub 1
go func() {
for i := 0; i < times; i++ {
atomic.AddInt32(&counter, -1)
}
defer done.Done()
}()
done.Wait()
fmt.Println("counter: ", counter, "times: ", times)
}