在之前的源码分析中,我们有多次看到atomic的出现,今天不妨我们看一下atomic的源码。
我们看一下atomic的源码文件:

这里说明一下,以.s为后缀的是汇编语言源代码文件,你可以并不懂汇编,没有关系。
主要看下asm.s,看一看到里面有调用runtime ∕ internal ∕ atomic,我们前去看一下这个文件夹,其中有个文件atomic_wasm.go。
atomic提供的是原子操作,atomic包中支持六种类型
- int32
- uint32
- int64
- uint64
- uintptr
- unsafe.Pointer
对于每一个类型,支持5种操作,我们以int32分别说明下这些操作:
SwapX
func SwapInt32(addr *int32, new int32) (old int32)
func Xchg(ptr *uint32, new uint32) uint32 { old := *ptr *ptr = new return old }
|
CompareAndSwapX
func CompareAndSwapInt32(addr *int32, old, new int32) (swapped bool)
func Cas(ptr *uint32, old, new uint32) bool { if *ptr == old { *ptr = new return true } return false }
|
AddX
func AddInt64(addr *int64, delta int64) (new int64)
func Xadd(ptr *uint32, delta int32) uint32 { new := *ptr + uint32(delta) *ptr = new return new }
|
LoadX
func LoadInt32(addr *int32) (val int32)
func Load(ptr *uint32) uint32 { return *ptr }
|
StoreX
func StoreInt32(addr *int32, val int32)
func Store(ptr *uint32, val uint32) { *ptr = val }
|
源码其实比较简单了,我就不过多说明了。
atomic.Value
另外,atomic对支持的类型做了扩展,atomic.Value被设计用来存储任意类型的数据。
type Value struct { v interface{} }
|
为了方便,定义了一个ifaceWords类型,它的作用是将interface{}
类型分解,得到其中的两个字段,作为interface的内部表示格式,typ代表原始类型,data代表真正的值。
type ifaceWords struct { typ unsafe.Pointer data unsafe.Pointer }
|
提供了Store和Load两个方法。
Store
func (v *Value) Store(x interface{}) { if x == nil { panic("sync/atomic: store of nil value into Value") } vp := (*ifaceWords)(unsafe.Pointer(v)) xp := (*ifaceWords)(unsafe.Pointer(&x)) for { typ := LoadPointer(&vp.typ) if typ == nil { runtime_procPin() if !CompareAndSwapPointer(&vp.typ, nil, unsafe.Pointer(^uintptr(0))) { runtime_procUnpin() continue } StorePointer(&vp.data, xp.data) StorePointer(&vp.typ, xp.typ) runtime_procUnpin() return } if uintptr(typ) == ^uintptr(0) { continue } if typ != xp.typ { panic("sync/atomic: store of inconsistently typed value into Value") } StorePointer(&vp.data, xp.data) return } }
|
Load
func (v *Value) Load() (x interface{}) { vp := (*ifaceWords)(unsafe.Pointer(v)) typ := LoadPointer(&vp.typ) if typ == nil || uintptr(typ) == ^uintptr(0) { return nil } data := LoadPointer(&vp.data) xp := (*ifaceWords)(unsafe.Pointer(&x)) xp.typ = typ xp.data = data return }
|
PS:解读的源码,如无特别说明,版本为1.15.6
参考: