mu是在阻塞操作時加的鎖;
read和dirty是兩個map啸如,可以把read理解為dirty的緩存(之后會詳解sync.map中的讀操作),且需要注意read和dirty中存儲的value都是指針;
misses是一個int值掀序,用于記錄在read中沒有讀到但在dirty中存在的值的次數(shù)(緩存未命中)且在misses值到一個閾值之后會發(fā)生一次dirty轉(zhuǎn)換為read(后面簡稱dr轉(zhuǎn)換)爹脾;
Load方法比較簡單,用于從map中獲取對應(yīng)key的value坡疼,主要邏輯是先從read中查找key彬呻,如果read中沒有找到,再去dirty中找柄瑰,并調(diào)用missLocked方法使misses值加一闸氮,missLocked方法中如果misses值大于dirty的長度后,會進(jìn)行一次dr轉(zhuǎn)換教沾。
注意:
a.這里用到了加鎖雙重檢查蒲跨,具體原因后面再解釋,sync.Map中很多地方都用了這個授翻。
b.amended是一個bool值或悲,當(dāng)dirty中有read中沒有的kv對時為true,只有在dr轉(zhuǎn)換發(fā)生后且沒有新的kv store進(jìn)來堪唐,dirty為nil巡语,才會為false
然后是Store方法,用于存儲kv
在調(diào)用Store方法時有兩種情況淮菠,一種是新增kv捌臊,一種是替換一個key的舊value值。如果是進(jìn)行值的替換兜材,sync.Map在進(jìn)行值的替換的時候理澎,先是直接在read中進(jìn)行替換,因為前面說過read和dirty中存儲的都是指針曙寡,所以在read中替換值糠爬,dirty也是可見的。如果替換失斁偈(該key在read中的value為expunged)或是read中沒有找到這個key烈评,則進(jìn)入下面的邏輯琳轿。首先如果確定該key在read中的value為expunged簇爆,則重新在dirty新增該kv硕糊,并將v進(jìn)行替換;如果是在read中沒有這個key蕊唐,但dirty中有屋摔,說明這個kv是新增到dirty的且之后未發(fā)生dr轉(zhuǎn)換,此時在dirty中對舊v進(jìn)行替換替梨;如果dirty中也沒有這個kv钓试,先判斷是否剛進(jìn)行過一次dr轉(zhuǎn)換(判斷amended的值)装黑,如果是則調(diào)用dirtylocked方法,然后在dirty中新增kv
dirtylocked方法將read中的v不為nil的kv復(fù)制到dirty中弓熏,read為nil的kv(后面可以知道這是被delete掉的kv)則將v設(shè)置為expunged恋谭,在下次dr轉(zhuǎn)換時即被永久刪除。
最后再看看Delete方法挽鞠,調(diào)用Delete后先看在read中是否有該kv疚颊,如果有,就調(diào)用e.delete方法進(jìn)行刪除信认,如果沒有再看dirty中是否存在該kv材义,如果有則用golang的delete方法從dirty中刪除
e.delete方法是是惰性刪除,調(diào)用后將read中該kv的v設(shè)置為nil狮杨。