原子操作是指在程序運行中不能被中斷的操作,原子操作是無鎖的常常是由CPU指令直接實現(xiàn),而鎖一般由操作系統(tǒng)的調(diào)度器實現(xiàn),所以原子操作的效率一般更高。
創(chuàng)新互聯(lián)自2013年創(chuàng)立以來,是專業(yè)互聯(lián)網(wǎng)技術(shù)服務(wù)公司,擁有項目成都網(wǎng)站制作、網(wǎng)站設(shè)計、外貿(mào)網(wǎng)站建設(shè)網(wǎng)站策劃,項目實施與項目整合能力。我們以讓每一個夢想脫穎而出為使命,1280元米脂做網(wǎng)站,已為上家服務(wù),為米脂各地企業(yè)和個人服務(wù),聯(lián)系電話:13518219792
golang中原子操作支持的類型有:int32、int64、uint32、uint64、uintptr、unsafe.Pointer
函數(shù)名以Add開頭,后面跟具體的類型。該方法接收兩個參數(shù),一個是內(nèi)存地址,一個是需要加上的數(shù)值,并返回加或者減后的結(jié)果。
// AddInt32 atomically adds delta to *addr and returns the new value.
func AddInt32(addr *int32, delta int32) (new int32)
// AddUint32 atomically adds delta to *addr and returns the new value.
// To subtract a signed positive constant value c from x, do AddUint32(&x, ^uint32(c-1)).
// In particular, to decrement x, do AddUint32(&x, ^uint32(0)).
func AddUint32(addr *uint32, delta uint32) (new uint32)
// AddInt64 atomically adds delta to *addr and returns the new value.
func AddInt64(addr *int64, delta int64) (new int64)
// AddUint64 atomically adds delta to *addr and returns the new value.
// To subtract a signed positive constant value c from x, do AddUint64(&x, ^uint64(c-1)).
// In particular, to decrement x, do AddUint64(&x, ^uint64(0)).
func AddUint64(addr *uint64, delta uint64) (new uint64)
// AddUintptr atomically adds delta to *addr and returns the new value.
func AddUintptr(addr *uintptr, delta uintptr) (new uintptr)
舉使用的例子:
func main() {
var a int32
atomic.AddInt32(&a,20)
fmt.Println("a 的值:",a)
atomic.AddInt32(&a,-8)
fmt.Println("a 的值:",a)
}
查看輸出
a 的值: 20
a 的值: 12
函數(shù)名以Load開頭,后面跟具體的類型。該方法接收一個地址,并返回該地址中的數(shù)據(jù)。
// LoadInt32 atomically loads *addr.
func LoadInt32(addr *int32) (val int32)
func LoadInt64(addr *int64) (val int64)
func LoadUint32(addr *uint32) (val uint32)
func LoadUint64(addr *uint64) (val uint64)
func LoadUintptr(addr *uintptr) (val uintptr)
func LoadPointer(addr *unsafe.Pointer) (val unsafe.Pointer)
函數(shù)名以Store開頭,后面跟具體的類型。該方法接收兩個參數(shù),一個是保存數(shù)據(jù)的地址,另外一個是要保存的值
該類主要負(fù)責(zé)將對應(yīng)的值保存在相應(yīng)的內(nèi)存地址中。
// StoreInt32 atomically stores val into *addr.
func StoreInt32(addr *int32, val int32)
func StoreInt64(addr *int64, val int64)
func StoreUint32(addr *uint32, val uint32)
func StoreUint64(addr *uint64, val uint64)
func StoreUintptr(addr *uintptr, val uintptr)
func StorePointer(addr *unsafe.Pointer, val unsafe.Pointer)
該操作簡稱 CAS(Compare And Swap)。 這類操作的前綴為 CompareAndSwap。該類方法接收3個參數(shù):數(shù)據(jù)的地址,舊的值,新值。比較地址內(nèi)的數(shù)據(jù)和舊數(shù)據(jù)是否相等。相等就把新值賦在該地址上并返回true。不等則直接返回false。
// CompareAndSwapInt32 executes the compare-and-swap operation for an int32 value.
func CompareAndSwapInt32(addr *int32, old, new int32) (swapped bool)
func CompareAndSwapInt64(addr *int64, old, new int64) (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 CompareAndSwapPointer(addr *unsafe.Pointer, old, new unsafe.Pointer) (swapped bool)
函數(shù)名以Swap開頭,后面跟具體的類型。該類方法接收一個地址和一個新值。將新值賦在地址上并返回舊的值。
// SwapInt32 atomically stores new into *addr and returns the previous *addr value.
func SwapInt32(addr *int32, new int32) (old int32)
func SwapInt64(addr *int64, new int64) (old int64)
func SwapUint32(addr *uint32, new uint32) (old uint32)
func SwapUint64(addr *uint64, new uint64) (old uint64)
func SwapUintptr(addr *uintptr, new uintptr) (old uintptr)
func SwapPointer(addr *unsafe.Pointer, new unsafe.Pointer) (old unsafe.Pointer)
對原子操作的類型的擴(kuò)展。從特定的類型擴(kuò)展到任意類型。
實現(xiàn)原子存儲任意類型的值。
// Store sets the value of the Value to x.
// All calls to Store for a given Value must use values of the same concrete type.
// Store of an inconsistent type panics, as does Store(nil).
func (v *Value) Store(x interface{}) {
if x == nil {
panic("sync/atomic: store of nil value into Value")
}
// 將現(xiàn)有的值和要寫入的值轉(zhuǎn)換為ifaceWords類型,這樣下一步就能獲取到它們的原始類型和真正的值
vp := (*ifaceWords)(unsafe.Pointer(v))
xp := (*ifaceWords)(unsafe.Pointer(&x))
for {
// 獲取現(xiàn)有的值的type
typ := LoadPointer(&vp.typ)
// 如果typ為nil說明這是第一次Store
if typ == nil {
// 如果你是第一次,就死死占住當(dāng)前的processor,不允許其他goroutine再搶
runtime_procPin()
// 使用CAS操作,先嘗試將typ設(shè)置為^uintptr(0)這個中間狀態(tài)
// 如果失敗,則證明已經(jīng)有別的線程搶先完成了賦值操作
// 那它就解除搶占鎖,然后重新回到 for 循環(huán)第一步
if !CompareAndSwapPointer(&vp.typ, nil, unsafe.Pointer(^uintptr(0))) {
runtime_procUnpin()
continue
}
// 如果設(shè)置成功,說明當(dāng)前goroutine中了jackpot
// 那么就原子性的更新對應(yīng)的指針,最后解除搶占鎖
StorePointer(&vp.data, xp.data)
StorePointer(&vp.typ, xp.typ)
runtime_procUnpin()
return
}
// 如果typ為^uintptr(0)說明第一次寫入還沒有完成,繼續(xù)循環(huán)等待
if uintptr(typ) == ^uintptr(0) {
continue
}
// 如果要寫入的類型和現(xiàn)有的類型不一致,則panic
if typ != xp.typ {
panic("sync/atomic: store of inconsistently typed value into Value")
}
// 更新data
StorePointer(&vp.data, xp.data)
return
}
}
提供了一致類型值的原子加載和存儲。 Value 的零值是從 Load 返回 nil。調(diào)用 Store 后,不得復(fù)制 Value。第一次調(diào)用store,就確定value的類型,以后每一次都必須是同樣的類型。如果store的值的類型和第一次不一樣或者store值是nil那么就會panic。
實現(xiàn)原子讀取任意類型的值
// Load returns the value set by the most recent Store.
// It returns nil if there has been no call to Store for this Value.
func (v *Value) Load() (x interface{}) {
// 將*Value指針類型轉(zhuǎn)換為*ifaceWords指針類型
vp := (*ifaceWords)(unsafe.Pointer(v))
// 原子性的獲取到v的類型typ的指針
typ := LoadPointer(&vp.typ)
// 如果沒有寫入或者正在寫入,先返回,^uintptr(0)代表過渡狀態(tài)
if typ == nil || uintptr(typ) == ^uintptr(0) {
return nil
}
// 原子性的獲取到v的真正的值data的指針,然后返回
data := LoadPointer(&vp.data)
xp := (*ifaceWords)(unsafe.Pointer(&x))
xp.typ = typ
xp.data = data
return
}
Load 返回最近的 Store 設(shè)置的值。如果沒有為此值調(diào)用 Store,則返回 nil。否則造出一個新的interface{}賦值進(jìn)去。