Go 讀寫鎖底層是怎麼實現的
「答案」(自由)
讀寫鎖的底層是基於互斥鎖實現的。
-
爲什麼有讀寫鎖,它解決了什麼問題?(使用場景)
-
它的底層原理是什麼?
在這裏我會結合 Go 中的讀寫鎖 RWMutex 進行介紹。
我們通過與 Mutex 對比得出答案。Mutex 是不區分 goroutine 對共享資源的操作行爲的,在讀操作、它會上鎖,在寫操作,它也會上鎖,當一段時間內,讀操作居多時,讀操作在 Mutex 的保護下也不得不變爲串行訪問,對性能的影響也就比較大了。
RWMutex 讀寫鎖的誕生爲了區分讀寫操作,在進行讀操作時,goroutine 就不必傻傻的等待了,而是可以併發地訪問共享資源,將串行讀變成了並行讀,提高了讀操作的性能。
讀寫鎖針對解決一類問題:readers-writes ,同時有多個讀或者多個寫操作時,只要有一個線程在執行寫操作,其他的線程都不能進行讀操作。
讀寫鎖其實有三種工作模型:
-
Read-perferring 優先讀設計,可能會導致寫飢餓
-
Write-prferring 優先寫設計,避免寫飢餓
-
不指定優先級 不區分優先級,解決飢餓問題
Go 中的讀寫鎖,工作模型是 Write-prferring 方案。
「答案」(欒龍生)
-
讀寫鎖解決問題
主要應用於寫操作少,讀操作多的場景。讀寫鎖滿足以下四條規則。
-
寫鎖需要阻塞寫鎖:一個協程擁有寫鎖時,其他協程寫鎖定需要阻塞;
-
寫鎖需要阻塞讀鎖:一個協程擁有寫鎖時,其他協程讀鎖定需要阻塞;
-
讀鎖需要阻塞寫鎖:一個協程擁有讀鎖時,其他協程寫鎖定需要阻塞;
-
讀鎖不能阻塞讀鎖:一個協程擁有讀鎖時,其他協程也可以擁有讀鎖。
-
讀寫鎖底層實現
讀寫鎖內部仍有一個互斥鎖,用於將多個寫操作隔離開來,其他幾個都用於隔離讀操作和寫操作。
源碼包
src/sync/rmmutex.go:RWMutex
中定義了讀寫鎖的數據結構
type RWMutex struct {
w Mutex // held if there are pending writers
writerSem uint32 // semaphore for writers to wait for completing readers
readerSem uint32 // semaphore for readers to wait for completing writers
readerCount int32 // number of pending readers
readerWait int32 // number of departing readers
}
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/CARzBDS3PSeH-EVrADvozA