網站首頁 編程語言 正文
1.go已經提供了鎖,為什么還需要atomic原子操作?
1.加鎖代價比較高,耗時多,需要上下文切換。加鎖解鎖在代碼層實現,而代碼是運行在用戶態空間中,對底層進行操作時需要從用戶態空間切換到內核空間,再由內核操作底層資源。耗時多
2.原子操作在用戶態可以完成,性能比互斥鎖高。原子操作在cpu層面支持的,cpu可以直接操作底層資源
3.原子操作需求步驟簡單,無需加鎖解鎖步驟
2.atomic原子操作為什么比mutex快?
1.原子操作快,是因為依賴于cpu指令,而不是依賴外部鎖。不會額外的上下文切換
2.原子操作能夠保證執行期間是連續且不會被中斷(變量不會被其他修改,mutex可能存在被其他修改的情況)
3.CAS
CAS是cpu硬件同步原語,是Compare And Swap的縮寫(比較并交換),原子操作中CAS,再sync/atomic包中,全部以ComparAndSwap開頭的函數名都是CAS操作
? ?go中CAS操作,是借用CPU提供的原子性指令來實現。CAS操作修改共享變量時,不需要對共享變量加鎖,而是通過類似樂觀鎖的方式進行檢查,本質還是不斷的占用CPU資源換取加鎖帶來的開銷(如上下文切換時間開銷)。
原子操作優勢:
? ?可以在不形成臨界區和創建互斥量的情況下完成并發安全的值替換操作。這可以大大的減少同步對程序性能的損耗。
原子操作劣勢:
? ?在被操作值被頻繁的變更的情況下,CAS操作并不那么容易成功。因為需要對ild值進行匹配,只有匹配成功了才進行下一步的修改。
當前atmomic包有以下幾種原子操作:
? ?Add,ComparAndSwap,Load,Store,Swap
4.互斥鎖與原子操作區別
互斥鎖目的:互斥鎖是用來保護一段邏輯的,保證并發安全。(比如操作數據庫保護)
原子操作目的:原子操作作用于一個變量的更新保護,保證并發安全(比如操作數據庫不能原子操作)
mutex底層實現:mutex由操作系統的調度器實現
原子操作底層實現:由底層硬件指令直接提供支持,這些指令在執行過程中不允許中斷,因此原子操作可以在無鎖的情況下保證并發安全,性能隨cpu的數量增多而線性擴展。
5.原子操作方法
5.1 atomic.AddInt32--增減
增減,操作方法的命名方式為AddXXX,保證對操作數進行原子的增減,支持的類型為int32、int64、uint32、uint64、uintptr,使用時以AddXXX就是對應的操作方法。
//加 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值與當前值是否一致,一致則把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 }
原文鏈接:https://www.cnblogs.com/guyouyin123/p/16565192.html
相關推薦
- 2022-06-08 Spring Boot Start之mqtt框架封裝
- 2022-11-27 Python+decimal完成精度計算的示例詳解_python
- 2022-08-23 Python?Pandas數據處理高頻操作詳解_python
- 2022-04-04 前端小技巧:ELement UI時間控件el-date-picker誤差8小時
- 2023-03-13 Pandas篩選某列過濾的方法_python
- 2022-11-27 C++常見的stl容器與相關操作?示例解析_C 語言
- 2022-05-05 Entity?Framework實現數據遷移_實用技巧
- 2022-08-20 在?pytorch?中實現計算圖和自動求導_python
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支