Go 語(yǔ)言 sync.RWMutex讀寫(xiě)鎖

2023-03-14 16:58 更新

原文鏈接:https://gopl-zh.github.io/ch9/ch9-03.html


9.3. sync.RWMutex讀寫(xiě)鎖

在100刀的存款消失時(shí)不做記錄多少還是會(huì)讓我們有一些恐慌,Bob寫(xiě)了一個(gè)程序,每秒運(yùn)行幾百次來(lái)檢查他的銀行余額。他會(huì)在家,在工作中,甚至?xí)谒氖謾C(jī)上來(lái)運(yùn)行這個(gè)程序。銀行注意到這些陡增的流量使得存款和取款有了延時(shí),因?yàn)樗械挠囝~查詢(xún)請(qǐng)求是順序執(zhí)行的,這樣會(huì)互斥地獲得鎖,并且會(huì)暫時(shí)阻止其它的goroutine運(yùn)行。

由于Balance函數(shù)只需要讀取變量的狀態(tài),所以我們同時(shí)讓多個(gè)Balance調(diào)用并發(fā)運(yùn)行事實(shí)上是安全的,只要在運(yùn)行的時(shí)候沒(méi)有存款或者取款操作就行。在這種場(chǎng)景下我們需要一種特殊類(lèi)型的鎖,其允許多個(gè)只讀操作并行執(zhí)行,但寫(xiě)操作會(huì)完全互斥。這種鎖叫作“多讀單寫(xiě)”鎖(multiple readers, single writer lock),Go語(yǔ)言提供的這樣的鎖是sync.RWMutex:

var mu sync.RWMutex
var balance int
func Balance() int {
    mu.RLock() // readers lock
    defer mu.RUnlock()
    return balance
}

Balance函數(shù)現(xiàn)在調(diào)用了RLock和RUnlock方法來(lái)獲取和釋放一個(gè)讀取或者共享鎖。Deposit函數(shù)沒(méi)有變化,會(huì)調(diào)用mu.Lock和mu.Unlock方法來(lái)獲取和釋放一個(gè)寫(xiě)或互斥鎖。

在這次修改后,Bob的余額查詢(xún)請(qǐng)求就可以彼此并行地執(zhí)行并且會(huì)很快地完成了。鎖在更多的時(shí)間范圍可用,并且存款請(qǐng)求也能夠及時(shí)地被響應(yīng)了。

RLock只能在臨界區(qū)共享變量沒(méi)有任何寫(xiě)入操作時(shí)可用。一般來(lái)說(shuō),我們不應(yīng)該假設(shè)邏輯上的只讀函數(shù)/方法也不會(huì)去更新某一些變量。比如一個(gè)方法功能是訪問(wèn)一個(gè)變量,但它也有可能會(huì)同時(shí)去給一個(gè)內(nèi)部的計(jì)數(shù)器+1(譯注:可能是記錄這個(gè)方法的訪問(wèn)次數(shù)啥的),或者去更新緩存——使即時(shí)的調(diào)用能夠更快。如果有疑惑的話,請(qǐng)使用互斥鎖。

RWMutex只有當(dāng)獲得鎖的大部分goroutine都是讀操作,而鎖在競(jìng)爭(zhēng)條件下,也就是說(shuō),goroutine們必須等待才能獲取到鎖的時(shí)候,RWMutex才是最能帶來(lái)好處的。RWMutex需要更復(fù)雜的內(nèi)部記錄,所以會(huì)讓它比一般的無(wú)競(jìng)爭(zhēng)鎖的mutex慢一些。



以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)