go 原子操作 atomic的使用
go語言提供的原子操作都是非侵入式的,它們由標(biāo)準(zhǔn)庫代碼包sync/atomic中的眾多函數(shù)代表。
我們調(diào)用sync/atomic中的幾個函數(shù)可以對幾種簡單的類型進行原子操作。這些類型包括int32,int64,uint32,uint64,uintptr,unsafe.Pointer,共6個。這些函數(shù)的原子操作共有5種:增或減,比較并交換、載入、存儲和交換它們提供了不同的功能,切使用的場景也有區(qū)別。
增或減
顧名思義,原子增或減即可實現(xiàn)對被操作值的增大或減少。因此該操作只能操作數(shù)值類型。
被用于進行增或減的原子操作都是以“Add”為前綴,并后面跟針對具體類型的名稱。
//方法源碼 func AddUint32(addr *uint32, delta uint32) (new uint32)增加
示例:(在原來的基礎(chǔ)上加n)
atomic.AddUint32(&addr,n)減
示例:(在原來的基礎(chǔ)上加n(n為負數(shù)))
atomic.AddUint32(*addr,uint32(int32(n))) //或 atomic.AddUint32(&addr,^uint32(-n-1))比較并交換
比較并交換----Compare And Swap 簡稱CAS
他是假設(shè)被操作的值未曾被改變(即與舊值相等),并一旦確定這個假設(shè)的真實性就立即進行值替換
如果想安全的并發(fā)一些類型的值,我們總是應(yīng)該優(yōu)先使用CAS
//方法源碼 func CompareAndSwapInt32(addr *int32, old, new int32) (swapped bool)示例:(如果addr和old相同,就用new代替addr)
ok:=atomic.CompareAndSwapInt32(&addr,old,new)載入
如果一個寫操作未完成,有一個讀操作就已經(jīng)發(fā)生了,這樣讀操作使很糟糕的。
為了原子的讀取某個值sync/atomic代碼包同樣為我們提供了一系列的函數(shù)。這些函數(shù)都以"Load"為前綴,意為載入。
//方法源碼 func LoadInt32(addr *int32) (val int32)示例
fun addValue(delta int32){for{v:=atomic.LoadInt32(&addr)if atomic.CompareAndSwapInt32(&v,addr,(delta+v)){break;}} }存儲
與讀操作對應(yīng)的是寫入操作,sync/atomic也提供了與原子的值載入函數(shù)相對應(yīng)的原子的值存儲函數(shù)。這些函數(shù)的名稱均以“Store”為前綴
在原子的存儲某個值的過程中,任何cpu都不會進行針對進行同一個值的讀或?qū)懖僮鳌H绻覀儼阉嗅槍Υ酥档膶懖僮鞫几臑樵硬僮?#xff0c;那么就不會出現(xiàn)針對此值的讀操作讀操作因被并發(fā)的進行而讀到修改了一半的情況。
原子操作總會成功,因為他不必關(guān)心被操作值的舊值是什么。
//方法源碼 func StoreInt32(addr *int32, val int32)示例
atomic.StoreInt32(被操作值的指針,新值) atomic.StoreInt32(&value,newaddr)交換
原子交換操作,這類函數(shù)的名稱都以“Swap”為前綴。
與CAS不同,交換操作直接賦予新值,不管舊值。
會返回舊值
//方法源碼 func SwapInt32(addr *int32, new int32) (old int32)示例
atomic.SwapInt32(被操作值的指針,新值)(返回舊值) oldval:=atomic.StoreInt32(&value,newaddr)?
總結(jié)
以上是生活随笔為你收集整理的go 原子操作 atomic的使用的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 树的宽度 递归法和非递归法
- 下一篇: go语言 sync.map遍历时删除可以