goland?-sync/atomic原子操作小結(jié)
1.go已經(jīng)提供了鎖,為什么還需要atomic原子操作?
1.加鎖代價比較高,耗時多,需要上下文切換。加鎖解鎖在代碼層實(shí)現(xiàn),而代碼是運(yùn)行在用戶態(tài)空間中,對底層進(jìn)行操作時需要從用戶態(tài)空間切換到內(nèi)核空間,再由內(nèi)核操作底層資源。耗時多
2.原子操作在用戶態(tài)可以完成,性能比互斥鎖高。原子操作在cpu層面支持的,cpu可以直接操作底層資源
3.原子操作需求步驟簡單,無需加鎖解鎖步驟
2.atomic原子操作為什么比mutex快?
1.原子操作快,是因?yàn)橐蕾囉赾pu指令,而不是依賴外部鎖。不會額外的上下文切換
2.原子操作能夠保證執(zhí)行期間是連續(xù)且不會被中斷(變量不會被其他修改,mutex可能存在被其他修改的情況)
3.CAS
CAS是cpu硬件同步原語,是Compare And Swap的縮寫(比較并交換),原子操作中CAS,再sync/atomic包中,全部以ComparAndSwap開頭的函數(shù)名都是CAS操作
go中CAS操作,是借用CPU提供的原子性指令來實(shí)現(xiàn)。CAS操作修改共享變量時,不需要對共享變量加鎖,而是通過類似樂觀鎖的方式進(jìn)行檢查,本質(zhì)還是不斷的占用CPU資源換取加鎖帶來的開銷(如上下文切換時間開銷)。
原子操作優(yōu)勢:
可以在不形成臨界區(qū)和創(chuàng)建互斥量的情況下完成并發(fā)安全的值替換操作。這可以大大的減少同步對程序性能的損耗。
原子操作劣勢:
在被操作值被頻繁的變更的情況下,CAS操作并不那么容易成功。因?yàn)樾枰獙ld值進(jìn)行匹配,只有匹配成功了才進(jìn)行下一步的修改。
當(dāng)前atmomic包有以下幾種原子操作:
Add,ComparAndSwap,Load,Store,Swap
4.互斥鎖與原子操作區(qū)別
互斥鎖目的:互斥鎖是用來保護(hù)一段邏輯的,保證并發(fā)安全。(比如操作數(shù)據(jù)庫保護(hù))
原子操作目的:原子操作作用于一個變量的更新保護(hù),保證并發(fā)安全(比如操作數(shù)據(jù)庫不能原子操作)
mutex底層實(shí)現(xiàn):mutex由操作系統(tǒng)的調(diào)度器實(shí)現(xiàn)
原子操作底層實(shí)現(xiàn):由底層硬件指令直接提供支持,這些指令在執(zhí)行過程中不允許中斷,因此原子操作可以在無鎖的情況下保證并發(fā)安全,性能隨cpu的數(shù)量增多而線性擴(kuò)展。
5.原子操作方法
5.1 atomic.AddInt32--增減
增減,操作方法的命名方式為AddXXX,保證對操作數(shù)進(jìn)行原子的增減,支持的類型為int32、int64、uint32、uint64、uintptr,使用時以AddXXX就是對應(yīng)的操作方法。
//加
func demo() {
var count int32 = 0
atomic.AddInt32(&count, 10)
fmt.Println(count) //10
}
//減
func demo() {
var count int32 = 0
atomic.AddInt32(&count, -10)
fmt.Println(count) //-10
}鎖和原子操作對比:
//Mutex鎖
func demo1() {
sta := time.Now().Unix()
count := 0
mux := sync.Mutex{}
wg := sync.WaitGroup{}
for i := 0; i < 10000; i++ {
wg.Add(1)
go func() {
defer wg.Done()
for j := 0; j < 10000; j++ {
mux.Lock()
count++
mux.Unlock()
}
}()
}
wg.Wait()
fmt.Println(count) //100000000
fmt.Println(time.Now().Unix() - sta) //10秒
}
//atomic原子操作:快2倍不止
func demo2() {
sta := time.Now().Unix()
wg := sync.WaitGroup{}
var count int32 = 0
for i := 0; i < 10000; i++ {
wg.Add(1)
go func() {
defer wg.Done()
for j := 0; j < 10000; j++ {
atomic.AddInt32(&count, 1)
}
}()
}
wg.Wait()
fmt.Println(count) //100000000
fmt.Println(time.Now().Unix() - sta) //4秒
}5.2 CAS-atomic.CompareAndSwapInt32--比較并替換
CompareAndSwap:比較并替換,類似樂觀鎖,先比較下old值與當(dāng)前值是否一致,一致則把new的值替換
操作方法的命名方式為CompareAndSwapXXX
//true
func demo3() {
var count int32 = 0
boo := atomic.CompareAndSwapInt32(&count, 0, 100)
fmt.Println(count) //100
fmt.Println(boo) //true
}
//false
func demo3() {
var count int32 = 0
boo := atomic.CompareAndSwapInt32(&count, 10, 100)
fmt.Println(count) //0
fmt.Println(boo) //false
}5.3 atomic.StoreInt32--寫操作
func demo3() {
var count int32 = 0
atomic.StoreInt32(&count, 666)
fmt.Println(count) //666
}5.4 atomic.LoadInt32--讀操作
func demo3() {
var count int32 = 0
atomic.StoreInt32(&count, 666)
val := atomic.LoadInt32(&count)
fmt.Println(val) //666
}5.5 atomic.SwapInt32--直接交換
atomic.SwapInt32:直接交換,并返回交換前的值
func demo3() {
var count int32 = 0
old := atomic.SwapInt32(&count, 100)
fmt.Println(old) //0
fmt.Println(count) //100
}到此這篇關(guān)于goland-sync/atomic原子操作的文章就介紹到這了,更多相關(guān)goland sync/atomic原子操作內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Go語言中實(shí)現(xiàn)完美錯誤處理實(shí)踐分享
Go?語言是一門非常流行的編程語言,由于其高效的并發(fā)編程和出色的網(wǎng)絡(luò)編程能力,越來越受到廣大開發(fā)者的青睞。本文我們就來深入探討一下Go?語言中的錯誤處理機(jī)制吧2023-04-04
Go-客戶信息關(guān)系系統(tǒng)的實(shí)現(xiàn)
這篇文章主要介紹了Go-客戶信息關(guān)系系統(tǒng)的實(shí)現(xiàn),本文章內(nèi)容詳細(xì),具有很好的參考價值,希望對大家有所幫助,需要的朋友可以參考下2023-01-01

