Go并發(fā)同步Mutex典型易錯(cuò)使用場(chǎng)景_第1頁
Go并發(fā)同步Mutex典型易錯(cuò)使用場(chǎng)景_第2頁
Go并發(fā)同步Mutex典型易錯(cuò)使用場(chǎng)景_第3頁
Go并發(fā)同步Mutex典型易錯(cuò)使用場(chǎng)景_第4頁
Go并發(fā)同步Mutex典型易錯(cuò)使用場(chǎng)景_第5頁
已閱讀5頁,還剩2頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡介

第Go并發(fā)同步Mutex典型易錯(cuò)使用場(chǎng)景目錄Mutex的4種易錯(cuò)使用場(chǎng)景1.Lock/Unlock不成對(duì)出現(xiàn)2.Copy已使用的Mutex3.重入4.死鎖解決策略

Mutex的4種易錯(cuò)使用場(chǎng)景

1.Lock/Unlock不成對(duì)出現(xiàn)

Lock/Unlock沒有成對(duì)出現(xiàn),就可能會(huì)出現(xiàn)死鎖或者是因?yàn)閁nlock一個(gè)未加鎖的Mutex而導(dǎo)致panic。

忘記Unlock的情形

代碼中有太多的if-else分支,可能在某個(gè)分支中漏寫了Unlock;在重構(gòu)的時(shí)候把Unlock給刪除了;Unlock誤寫成了Lock。

忘記Lock的情形一般是誤刪除了或者注釋掉了Lock。

eg:

funcmain(){

varmusync.Mutex

defermu.Unlock()

fmt.Println("oh,missingLock!")

errorresult:

2.Copy已使用的Mutex

實(shí)際上sync包下的同步原語在使用后都是不可復(fù)制的,原因在于Mutex是有狀態(tài)的,其state的值時(shí)刻在變化,如果復(fù)制一個(gè)已經(jīng)加鎖的Metux對(duì)象給一個(gè)新的變量,可能這個(gè)變量剛初始化就顯示被加鎖了,這顯然是不合理的。

eg:以下代碼在調(diào)用foo函數(shù)的時(shí)候,調(diào)用者會(huì)復(fù)制Mutex變量c作為foo函數(shù)的參數(shù),不幸的是,復(fù)制之前已經(jīng)使用了這個(gè)鎖,這就導(dǎo)致,復(fù)制的Counter是一個(gè)帶狀態(tài)Counter,從而會(huì)導(dǎo)致死鎖。

typeCounterstruct{

sync.Mutex

Countint

funcmain(){

varcCounter

c.Lock()

deferc.Unlock()

c.Count++

foo(c)//復(fù)制鎖

//這里Counter的參數(shù)是通過復(fù)制的方式傳入的

funcfoo(cCounter){

c.Lock()

deferc.Unlock()

fmt.Println("infoo")

errorresult:還好有Go的協(xié)程死鎖檢查機(jī)制,程序運(yùn)行后會(huì)快速失敗而不是一直hang住。

GoVet指令

我們當(dāng)然不想程序運(yùn)行了才發(fā)現(xiàn)死鎖,我們可以通過govet指令來在運(yùn)行前檢查我們的代碼是否存在lockcopy問題:

檢查原理

檢查是通過copylock分析器靜態(tài)分析實(shí)現(xiàn)的。這個(gè)分析器會(huì)分析函數(shù)調(diào)用、range遍歷、復(fù)制、聲明、函數(shù)返回值等位置,有沒有鎖的值copy的情景,以此來判斷有沒有問題。

通過源碼我們可以看到實(shí)現(xiàn)了Lock或者Unlock接口的struct都支持copylock檢查。

varlockerType*types.Interface

//Constructasync.Lockerinterfacetype.

funcinit(){

nullary:=types.NewSignature(nil,nil,nil,false)//func()

methods:=[]*types.Func{

types.NewFunc(token.NoPos,nil,"Lock",nullary),

types.NewFunc(token.NoPos,nil,"Unlock",nullary),

lockerType=types.NewInterface(methods,nil).Complete()

3.重入

Mutex不像Java中的ReentrantLock擁有可重入的功能,主要是因?yàn)槠鋵?shí)現(xiàn)中沒有標(biāo)記位記錄哪個(gè)goroutine擁有這把鎖,所以Mutex是一個(gè)不可重入鎖,而一旦誤用Mutex的重入就會(huì)報(bào)錯(cuò)。

eg:

funcfoo(lsync.Locker){

fmt.Println("infoo")

l.Lock()

bar(l)

l.Unlock()

funcbar(lsync.Locker){

l.Lock()

fmt.Println("inbar")

l.Unlock()

funcmain(){

l:=amp;sync.Mutex{}

foo(l)

errorresult:我們可以看到當(dāng)在bar方法中嘗試再次獲取鎖時(shí),獲取不到,觸發(fā)了死鎖。

4.死鎖

兩個(gè)或兩個(gè)以上的進(jìn)程(或線程,goroutine)

執(zhí)行過程中,因爭奪共享資源而處于一種互相等待的狀態(tài),如果沒有外部干涉,它們都將無法推進(jìn)下去,此時(shí),我們稱系統(tǒng)處于死鎖狀態(tài)或系統(tǒng)產(chǎn)生了死鎖。

死鎖產(chǎn)生的4個(gè)必要條件

如果想避免死鎖,我們只要思考如何打破以下任意條件就可以。

1.互斥:至少一個(gè)資源是被排他性獨(dú)享的,其他線程必須處于等待狀態(tài),直到資源被釋放。2.持有和等待:goroutine持有一個(gè)資源,并且還在請(qǐng)求其它goroutine持有的資源,也就是咱們常說的吃著碗里,看著鍋里的意思。3.不可剝奪:資源只能由持有它的goroutine來釋放。4.環(huán)路等待:一般來說,存在一組等待進(jìn)程,P={P1,P2,,PN},P1等待P2持有的

資源,P2等待P3持有的資源,依此類推,最后是PN等待P1持有的資源,這就形成

了一個(gè)環(huán)路等待的死結(jié)。

eg:在這里我們以辦理居住證業(yè)務(wù),舉一個(gè)簡單的環(huán)路等待導(dǎo)致死鎖的例子:

//辦理居住證

funcmain(){

//網(wǎng)簽中心證明

varpsCertificatesync.Mutex

//社區(qū)證明

varpropertyCertificatesync.Mutex

varwgsync.WaitGroup

wg.Add(2)//需要網(wǎng)簽中心和社區(qū)都處理

//網(wǎng)簽中心處理goroutine

gofunc(){

deferwg.Done()//網(wǎng)簽中心處理完成

psCertificate.Lock()

deferpsCertificate.Unlock()

//檢查材料

time.Sleep(5*time.Second)

//請(qǐng)求社區(qū)的證明

propertyCertificate.Lock()

propertyCertificate.Unlock()

//社區(qū)處理goroutine

gofunc(){

deferwg.Done()//社區(qū)處理完成

propertyCertificate.Lock()

deferpropertyCertificate.Unlock()

//檢查材料

time.Sleep(5*time.Second)

//請(qǐng)求網(wǎng)簽中心的證明

psCertificate.Lock()

psCertificate.Unlock()

wg.Wait()

fmt.Println("成功完成")

errorresult:

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(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)論