針對(duì)Golang 1.9的sync.RWMutex進(jìn)行分析,與Golang 1.10基本一樣除了將panic改為了throw之外其他的都一樣。
RWMutex是讀寫互斥鎖。鎖可以由任意數(shù)量的讀取器或單個(gè)寫入器來(lái)保持。
RWMutex的零值是一個(gè)解鎖的互斥鎖。
以下代碼均去除race競(jìng)態(tài)檢測(cè)代碼
源代碼位置:sync\rwmutex.go
結(jié)構(gòu)體
type RWMutex struct {
w Mutex // 互斥鎖
writerSem uint32 // 寫鎖信號(hào)量
readerSem uint32 // 讀鎖信號(hào)量
readerCount int32 // 讀鎖計(jì)數(shù)器
readerWait int32 // 獲取寫鎖時(shí)需要等待的讀鎖釋放數(shù)量
}
常量
const rwmutexMaxReaders = 1 30 // 支持最多2^30個(gè)讀鎖
方法
Lock
提供寫鎖操作.
func (rw *RWMutex) Lock() {
// 競(jìng)態(tài)檢測(cè)
if race.Enabled {
_ = rw.w.state
race.Disable()
}
// 使用Mutex鎖
rw.w.Lock()
// Announce to readers there is a pending writer.
r := atomic.AddInt32(rw.readerCount, -rwmutexMaxReaders) + rwmutexMaxReaders
// Wait for active readers.
if r != 0 atomic.AddInt32(rw.readerWait, r) != 0 {
runtime_Semacquire(rw.writerSem)
}
// 競(jìng)態(tài)檢測(cè)
if race.Enabled {
race.Enable()
race.Acquire(unsafe.Pointer(rw.readerSem))
race.Acquire(unsafe.Pointer(rw.writerSem))
}
}
RLock
提供讀鎖操作,
func (rw *RWMutex) RLock() {
// 競(jìng)態(tài)檢測(cè)
if race.Enabled {
_ = rw.w.state
race.Disable()
}
// 每次goroutine獲取讀鎖時(shí),readerCount+1
// 如果寫鎖已經(jīng)被獲取,那么readerCount在-rwmutexMaxReaders與0之間,這時(shí)掛起獲取讀鎖的goroutine,
// 如果寫鎖沒有被獲取,那么readerCount>0,獲取讀鎖,不阻塞
// 通過(guò)readerCount判斷讀鎖與寫鎖互斥,如果有寫鎖存在就掛起goroutine,多個(gè)讀鎖可以并行
if atomic.AddInt32(rw.readerCount, 1) 0 {
// 將goroutine排到G隊(duì)列的后面,掛起goroutine
runtime_Semacquire(rw.readerSem)
}
// 競(jìng)態(tài)檢測(cè)
if race.Enabled {
race.Enable()
race.Acquire(unsafe.Pointer(rw.readerSem))
}
}
RLocker
可以看到RWMutex實(shí)現(xiàn)接口Locker.
type Locker interface {
Lock()
Unlock()
}
而方法RLocker就是將RWMutex轉(zhuǎn)換為L(zhǎng)ocker.
func (rw *RWMutex) RLocker() Locker {
return (*rlocker)(rw)
}
總結(jié)
讀寫互斥鎖的實(shí)現(xiàn)比較有技巧性一些,需要幾點(diǎn)
- 讀鎖不能阻塞讀鎖,引入readerCount實(shí)現(xiàn)
- 讀鎖需要阻塞寫鎖,直到所以讀鎖都釋放,引入readerSem實(shí)現(xiàn)
- 寫鎖需要阻塞讀鎖,直到所以寫鎖都釋放,引入wirterSem實(shí)現(xiàn)
- 寫鎖需要阻塞寫鎖,引入Metux實(shí)現(xiàn)
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
您可能感興趣的文章:- GO語(yǔ)言并發(fā)編程之互斥鎖、讀寫鎖詳解
- 詳解Golang互斥鎖內(nèi)部實(shí)現(xiàn)
- Go語(yǔ)言實(shí)現(xiàn)互斥鎖、隨機(jī)數(shù)、time、List