golang sync.Map分析,設計思想:讀多寫少
sync.Map
結構體
type Map struct {
mu Mutex
read atomic.Value // readOnly
dirty map[interface{}]*entry
misses int
}
sync.Map設計思想(讀多寫少)
sync.Map 採用“空間換時間”的機制,sync.Map結構體冗餘了兩個資料結構,分別是:read
和dirty
;
寫值的時候得通過 Store 方法,讀的時候使用方法 Load 來讀取。
與map+RWMutex的實現併發的方式相比,減少了加鎖對效能的影響。
它做了一些優化:可以無鎖訪問read map,而且會優先操作read map,倘若只操作rede map就可以滿足要求,那就不用去操作write map(dirty)。
所以在某些特定場景中它發生鎖競爭的頻率會遠遠小於map + RWMutex的實現方式。
優點:適合讀多寫少的場景;
缺點:如果是寫多的場景,會導致read map快取失效,需要加鎖,衝突突變,效能急劇下降。
map併發寫就用map+sync.Mutex效率更高,sync.Map效能比較低1580ns/op
珂哥講技術:
sync.Map有兩個陣列,read陣列和dirty陣列(髒陣列),寫入map他會發現,read裡面沒有就寫到dirty數組裡面1:1,2:2 ,想讀key=1的值發現read數組裡面沒有,加鎖從dirty數組裡面找,找到不到命中計數器++(miss計數器),當miss++>len(dirty),它就會把dirty裡面的資料拷貝到read數組裡面,然後把dirty裡面的資料清理掉,讀是不加鎖特別快,
改寫1:11,首先在read陣列把11進行原子操作,資料交換,同時會在dirty數組裡面寫進去;寫一個新的資料3會寫到dirty數組裡面,同樣原理read的時候沒有命中就去dirty數組裡面數據拷貝到read數組裡面,清理到dirty陣列的全部資料 。所以為什麼sync.Map讀快是因為不加鎖,寫慢是因為加鎖,同時在寫的時候還會再去讀一次read陣列,造成時間消耗的比較多。