一文帶你深入探究Go語(yǔ)言中的sync.Map_第1頁(yè)
一文帶你深入探究Go語(yǔ)言中的sync.Map_第2頁(yè)
一文帶你深入探究Go語(yǔ)言中的sync.Map_第3頁(yè)
一文帶你深入探究Go語(yǔ)言中的sync.Map_第4頁(yè)
一文帶你深入探究Go語(yǔ)言中的sync.Map_第5頁(yè)
已閱讀5頁(yè),還剩3頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

第一文帶你深入探究Go語(yǔ)言中的sync.Map目錄1.Map的基本實(shí)現(xiàn)原理2.sync.Map的實(shí)現(xiàn)原理2.1sync.Map的結(jié)構(gòu)體定義2.2sync.Map的讀取實(shí)現(xiàn)2.3sync.Map的寫(xiě)入實(shí)現(xiàn)2.4sync.Map的刪除實(shí)現(xiàn)2.5sync.Map的遍歷實(shí)現(xiàn)在Go語(yǔ)言中,有一個(gè)非常實(shí)用的并發(fā)安全的Map實(shí)現(xiàn):sync.Map,它是在Go1.9版本中引入的。相比于標(biāo)準(zhǔn)庫(kù)中的map,它的最大特點(diǎn)就是可以在并發(fā)情況下安全地讀寫(xiě),而不需要加鎖。在這篇博客中,我們將深入探討sync.Map的基本原理,幫助讀者更好地理解并使用這個(gè)并發(fā)安全的Map。

1.Map的基本實(shí)現(xiàn)原理

在介紹sync.Map的基本實(shí)現(xiàn)原理之前,我們需要先了解一下Go語(yǔ)言標(biāo)準(zhǔn)庫(kù)中的map實(shí)現(xiàn)原理。在Go中,map是基于哈希表實(shí)現(xiàn)的。當(dāng)我們向map中添加元素時(shí),它會(huì)根據(jù)key計(jì)算出一個(gè)哈希值,然后將這個(gè)值映射到一個(gè)桶中。如果該桶中已經(jīng)有了元素,它會(huì)遍歷桶中的元素,查找是否已經(jīng)存在相同的key,如果存在就更新對(duì)應(yīng)的值,否則就添加一個(gè)新的鍵值對(duì)。

下面是一個(gè)簡(jiǎn)單的map示例:

m:=make(map[string]int)

m["a"]=1

m["b"]=2

fmt.Println(m["a"])//Output:1

當(dāng)我們運(yùn)行這段代碼時(shí),Go語(yǔ)言會(huì)自動(dòng)幫我們分配一個(gè)哈希表和若干個(gè)桶,然后將鍵值對(duì)添加到對(duì)應(yīng)的桶中。這樣,當(dāng)我們需要訪問(wèn)某個(gè)key對(duì)應(yīng)的值時(shí),Go語(yǔ)言會(huì)根據(jù)哈希值快速定位到對(duì)應(yīng)的桶,然后遍歷桶中的元素,查找是否有相同的key,如果找到了就返回對(duì)應(yīng)的值。

2.sync.Map的實(shí)現(xiàn)原理

sync.Map是Go語(yǔ)言標(biāo)準(zhǔn)庫(kù)中的一個(gè)并發(fā)安全的Map實(shí)現(xiàn),它可以在并發(fā)情況下安全地讀寫(xiě),而不需要加鎖。那么,它是如何實(shí)現(xiàn)這種并發(fā)安全性的呢?下面我們就來(lái)一步步地解析sync.Map的實(shí)現(xiàn)原理。

2.1sync.Map的結(jié)構(gòu)體定義

首先,讓我們來(lái)看一下sync.Map的結(jié)構(gòu)體定義:

typeMapstruct{

musync.Mutex

readatomic.Value//readOnly

dirtymap[interface{}]interface{}

missesint

dirtyLockeduintptr

}

從上面的代碼中可以看出,sync.Map的實(shí)現(xiàn)主要是依賴于一個(gè)互斥鎖(sync.Mutex)和兩個(gè)map(read和dirty)。其中,read和dirty的作用分別是什么呢?我們先來(lái)看一下read的定義:

typereadOnlystruct{

mmap[interface{}]interface{}

amendedbool

}

可以看到,read只有一個(gè)成員m,它是一個(gè)map類型。而amended則表示read中的鍵值對(duì)是否被修改過(guò)。接下來(lái),我們來(lái)看一下dirty的定義:

typedirtystruct{

mmap[interface{}]interface{}

dirtymap[interface{}]bool

missesint

}

和read不同的是,dirty中包含了兩個(gè)map:m和dirty。其中,m存儲(chǔ)了被修改過(guò)的鍵值對(duì),而dirty則存儲(chǔ)了哪些鍵值對(duì)被修改過(guò)。

2.2sync.Map的讀取實(shí)現(xiàn)

在sync.Map中,讀取操作非常簡(jiǎn)單,直接從readOnly中的m中查找即可。如果readOnly中的鍵值對(duì)被修改過(guò),則需要從dirty中查找。讀取操作的實(shí)現(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中查找鍵值對(duì)。如果鍵值對(duì)不存在且readOnly中的鍵值對(duì)被修改過(guò),則需要獲取互斥鎖,并重新從readOnly中查找。如果還是沒(méi)有找到,那么就從dirty中查找。

2.3sync.Map的寫(xiě)入實(shí)現(xiàn)

在sync.Map中,寫(xiě)入操作需要分兩步完成。首先,我們需要判斷readOnly中的鍵值對(duì)是否被修改過(guò),如果沒(méi)有被修改過(guò),則直接將鍵值對(duì)添加到readOnly中的m中即可。否則,我們需要獲取互斥鎖,然后將鍵值對(duì)添加到dirty中的m中,并將對(duì)應(yīng)的鍵添加到dirty中的dirty中。寫(xiě)入操作的實(shí)現(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中查找鍵值對(duì)。如果鍵值對(duì)不存在且readOnly中的鍵值對(duì)沒(méi)有被修改過(guò),則需要獲取互斥鎖,并重新從readOnly中查找。如果還是沒(méi)有找到,則將鍵值對(duì)添加到readOnly中的m中,并將amended設(shè)置為true。否則,我們需要獲取互斥鎖,并將鍵值對(duì)添加到dirty中的m中,并將對(duì)應(yīng)的鍵添加到dirty中的dirty中。如果dirty中已經(jīng)存在該鍵,則只需要更新dirty中的鍵值即可。如果dirty中沒(méi)有該鍵,則需要在dirty中添加該鍵,并將該鍵的dirty置為true。

接下來(lái),我們需要判斷dirty是否被鎖定。如果dirty被鎖定,則直接退出函數(shù)。否則,我們需要將readOnly中的amended設(shè)置為true,并將readOnly存儲(chǔ)回read中。

2.4sync.Map的刪除實(shí)現(xiàn)

在sync.Map中,刪除操作也需要分兩步完成。首先,我們需要判斷readOnly中的鍵值對(duì)是否被修改過(guò),如果沒(méi)有被修改過(guò),則直接從readOnly中的m中刪除鍵值對(duì)即可。否則,我們需要獲取互斥鎖,然后將鍵添加到dirty中的dirty中,并將dirty中的對(duì)應(yīng)鍵的值設(shè)置為false。刪除操作的實(shí)現(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中查找鍵值對(duì)。如果鍵值對(duì)存在或者readOnly中的鍵值對(duì)被修改過(guò),則需要獲取互斥鎖,并重新從readOnly中查找。如果還是沒(méi)有找到,則將鍵添加到dirty中的dirty中,并將dirty中的對(duì)應(yīng)鍵的值設(shè)置為false。接下來(lái),我們需要判斷dirty是否為nil,如果為nil,則需要將dirty初始化為一個(gè)空map。然后,我們將鍵添加到dirty中,并將dirty中的對(duì)應(yīng)鍵的值設(shè)置為true。最后,我們將readOnly中的amended設(shè)置為true,并將readOnly存儲(chǔ)回read中。

2.5sync.Map的遍歷實(shí)現(xiàn)

在sync.Map中,遍歷操作需要將readOnly和dirty中的所有鍵值對(duì)進(jìn)行合并,并返回所有未被刪除的鍵值對(duì)。遍歷操作的實(shí)現(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中獲取所有的鍵值對(duì),并檢查是否有鍵值對(duì)被修改過(guò)。如果鍵值對(duì)被修改過(guò),則需要獲取互斥鎖,并將readOnly和dirty中的鍵值對(duì)合并,然后將合并后的鍵值對(duì)存儲(chǔ)回readOnly中,并將dirty設(shè)置為nil。接下來(lái),我們遍歷readOnly中的所有鍵值對(duì),并調(diào)用f函數(shù)來(lái)處理鍵值對(duì)。如果f函數(shù)返回false,則遍歷過(guò)程結(jié)束

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論