




版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
第一文帶你深入探究Go語言中的sync.Map目錄1.Map的基本實現(xiàn)原理2.sync.Map的實現(xiàn)原理2.1sync.Map的結構體定義2.2sync.Map的讀取實現(xiàn)2.3sync.Map的寫入實現(xiàn)2.4sync.Map的刪除實現(xiàn)2.5sync.Map的遍歷實現(xiàn)在Go語言中,有一個非常實用的并發(fā)安全的Map實現(xiàn):sync.Map,它是在Go1.9版本中引入的。相比于標準庫中的map,它的最大特點就是可以在并發(fā)情況下安全地讀寫,而不需要加鎖。在這篇博客中,我們將深入探討sync.Map的基本原理,幫助讀者更好地理解并使用這個并發(fā)安全的Map。
1.Map的基本實現(xiàn)原理
在介紹sync.Map的基本實現(xiàn)原理之前,我們需要先了解一下Go語言標準庫中的map實現(xiàn)原理。在Go中,map是基于哈希表實現(xiàn)的。當我們向map中添加元素時,它會根據(jù)key計算出一個哈希值,然后將這個值映射到一個桶中。如果該桶中已經有了元素,它會遍歷桶中的元素,查找是否已經存在相同的key,如果存在就更新對應的值,否則就添加一個新的鍵值對。
下面是一個簡單的map示例:
m:=make(map[string]int)
m["a"]=1
m["b"]=2
fmt.Println(m["a"])//Output:1
當我們運行這段代碼時,Go語言會自動幫我們分配一個哈希表和若干個桶,然后將鍵值對添加到對應的桶中。這樣,當我們需要訪問某個key對應的值時,Go語言會根據(jù)哈希值快速定位到對應的桶,然后遍歷桶中的元素,查找是否有相同的key,如果找到了就返回對應的值。
2.sync.Map的實現(xiàn)原理
sync.Map是Go語言標準庫中的一個并發(fā)安全的Map實現(xiàn),它可以在并發(fā)情況下安全地讀寫,而不需要加鎖。那么,它是如何實現(xiàn)這種并發(fā)安全性的呢?下面我們就來一步步地解析sync.Map的實現(xiàn)原理。
2.1sync.Map的結構體定義
首先,讓我們來看一下sync.Map的結構體定義:
typeMapstruct{
musync.Mutex
readatomic.Value//readOnly
dirtymap[interface{}]interface{}
missesint
dirtyLockeduintptr
}
從上面的代碼中可以看出,sync.Map的實現(xiàn)主要是依賴于一個互斥鎖(sync.Mutex)和兩個map(read和dirty)。其中,read和dirty的作用分別是什么呢?我們先來看一下read的定義:
typereadOnlystruct{
mmap[interface{}]interface{}
amendedbool
}
可以看到,read只有一個成員m,它是一個map類型。而amended則表示read中的鍵值對是否被修改過。接下來,我們來看一下dirty的定義:
typedirtystruct{
mmap[interface{}]interface{}
dirtymap[interface{}]bool
missesint
}
和read不同的是,dirty中包含了兩個map:m和dirty。其中,m存儲了被修改過的鍵值對,而dirty則存儲了哪些鍵值對被修改過。
2.2sync.Map的讀取實現(xiàn)
在sync.Map中,讀取操作非常簡單,直接從readOnly中的m中查找即可。如果readOnly中的鍵值對被修改過,則需要從dirty中查找。讀取操作的實現(xiàn)代碼如下:
func(m*Map)Load(keyinterface{})(valueinterface{},okbool){
read,_:=m.read.Load().(readOnly)
value,ok=read.m[key]
if!okread.amended{
m.mu.Lock()
read,_=m.read.Load().(readOnly)
value,ok=read.m[key]
if!okread.amended{
value,ok=read.m[key]
m.mu.Unlock()
return
}
在這段代碼中,我們首先從readOnly中的m中查找鍵值對。如果鍵值對不存在且readOnly中的鍵值對被修改過,則需要獲取互斥鎖,并重新從readOnly中查找。如果還是沒有找到,那么就從dirty中查找。
2.3sync.Map的寫入實現(xiàn)
在sync.Map中,寫入操作需要分兩步完成。首先,我們需要判斷readOnly中的鍵值對是否被修改過,如果沒有被修改過,則直接將鍵值對添加到readOnly中的m中即可。否則,我們需要獲取互斥鎖,然后將鍵值對添加到dirty中的m中,并將對應的鍵添加到dirty中的dirty中。寫入操作的實現(xiàn)代碼如下:
func(m*Map)Store(key,valueinterface{}){
read,_:=m.read.Load().(readOnly)
ifv,ok:=read.m[key];!ok!read.amended{
m.mu.Lock()
read,_=m.read.Load().(readOnly)
ifv,ok:=read.m[key];!ok{
read=readOnly{m:read.m,amended:true}
read.m[key]=value
m.read.Store(read)
m.mu.Unlock()
}else{
m.mu.Lock()
dirty:=m.dirtyLocked!=0
if!dirty{
m.dirtyLocked=1
m.dirty=make(map[interface{}]interface{})
m.dirty[key]=value
if!ok{
m.dirty[key]=value
m.dirty[key]=true
ifdirty{
m.mu.Unlock()
return
m.read.Store(readOnly{m:read.m,amended:true})
m.mu.Unlock()
}
在這段代碼中,我們首先從readOnly中的m中查找鍵值對。如果鍵值對不存在且readOnly中的鍵值對沒有被修改過,則需要獲取互斥鎖,并重新從readOnly中查找。如果還是沒有找到,則將鍵值對添加到readOnly中的m中,并將amended設置為true。否則,我們需要獲取互斥鎖,并將鍵值對添加到dirty中的m中,并將對應的鍵添加到dirty中的dirty中。如果dirty中已經存在該鍵,則只需要更新dirty中的鍵值即可。如果dirty中沒有該鍵,則需要在dirty中添加該鍵,并將該鍵的dirty置為true。
接下來,我們需要判斷dirty是否被鎖定。如果dirty被鎖定,則直接退出函數(shù)。否則,我們需要將readOnly中的amended設置為true,并將readOnly存儲回read中。
2.4sync.Map的刪除實現(xiàn)
在sync.Map中,刪除操作也需要分兩步完成。首先,我們需要判斷readOnly中的鍵值對是否被修改過,如果沒有被修改過,則直接從readOnly中的m中刪除鍵值對即可。否則,我們需要獲取互斥鎖,然后將鍵添加到dirty中的dirty中,并將dirty中的對應鍵的值設置為false。刪除操作的實現(xiàn)代碼如下:
func(m*Map)Delete(keyinterface{}){
read,_:=m.read.Load().(readOnly)
if_,ok:=read.m[key];ok||read.amended{
m.mu.Lock()
read,_=m.read.Load().(readOnly)
if_,ok:=read.m[key];ok||read.amended{
ifm.dirty==nil{
m.dirty=make(map[interface{}]interface{})
m.dirty[key]=false
m.dirty[key]=true
m.read.Store(readOnly{m:read.m,amended:true})
m.mu.Unlock()
}
在這段代碼中,我們首先從readOnly中的m中查找鍵值對。如果鍵值對存在或者readOnly中的鍵值對被修改過,則需要獲取互斥鎖,并重新從readOnly中查找。如果還是沒有找到,則將鍵添加到dirty中的dirty中,并將dirty中的對應鍵的值設置為false。接下來,我們需要判斷dirty是否為nil,如果為nil,則需要將dirty初始化為一個空map。然后,我們將鍵添加到dirty中,并將dirty中的對應鍵的值設置為true。最后,我們將readOnly中的amended設置為true,并將readOnly存儲回read中。
2.5sync.Map的遍歷實現(xiàn)
在sync.Map中,遍歷操作需要將readOnly和dirty中的所有鍵值對進行合并,并返回所有未被刪除的鍵值對。遍歷操作的實現(xiàn)代碼如下:
func(m*Map)Range(ffunc(key,valueinterface{})bool){
read,_:=m.read.Load().(readOnly)
ifread.amended{
m.mu.Lock()
read,_=m.read.Load().(readOnly)
ifread.amended{
read=readOnly{
m:merge(read.m,m.dirty),
read.amended=false
m.read.Store(read)
m.dirty=nil
m.mu.Unlock()
fork,v:=rangeread.m{
if!f(k,v){
break
funcmerge(m1,m2map[interface{}]interface{})map[interface{}]interface{}{
iflen(m1)==0len(m2)==0{
returnnil
iflen(m1)==0{
returnm2
iflen(m2)==0{
returnm1
m:=make(map[interface{}]interface{})
fork,v:=rangem1{
m[k]=v
fork,v:=rangem2{
if_,ok:=m[k];!ok||!v.(bool){
m[k]=v
returnm
}
在這段代碼中,我們首先從readOnly中獲取所有的鍵值對,并檢查是否有鍵值對被修改過。如果鍵值對被修改過,則需要獲取互斥鎖,并將readOnly和dirty中的鍵值對合并,然后將合并后的鍵值對存儲回readOnly中,并將dirty設置為nil。接下來,我們遍歷readOnly中的所有鍵值對,并調用f函數(shù)來處理鍵值對。如果f函數(shù)返回false,則遍歷過程結束
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
- 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 展覽策劃與管理86課件
- 儀容禮儀13課件
- 信用風險模型的可解釋性與可視化研究-洞察及研究
- 2025年智能定制化商務用車租賃與一體化維護保養(yǎng)服務協(xié)議
- 2025年高端商務中心物業(yè)服務質量保障及優(yōu)化委托合同
- 2025年度珠寶首飾CIF出口貿易合作協(xié)議范本
- 2025建筑工程設計委托合同范本
- 2025年新能源研發(fā)保密協(xié)議:風力發(fā)電技術秘密保護合同
- 2025年智能化養(yǎng)殖場租賃服務保證金協(xié)議
- 2025年專業(yè)安保團隊引進與高端智能安防設備更新服務合同
- 收納整理培訓課件
- 輸液港及護理課件
- 食品營養(yǎng)與食品安全(食品安全)
- 干細胞臨床研究質量管理手冊
- 公立醫(yī)院 財務分析報告
- 建設用地報批服務投標方案(技術方案)
- 發(fā)展?jié)h語初級讀寫第一課知識介紹
- 《項目采購與合同管理》 課件 徐水太 第4-6章 工程項目采購、項目采購控制、PPP項目采購與合同管理
- 淺析半導體集成電路芯片廠房建筑設計
- 弱電工程施工重點難點分析
- 脊椎告訴你的健康秘密
評論
0/150
提交評論