比較粗糙簡單,思路就是用一個mutex作爲資源鎖,用兩個整數記錄讀者數和寫者數,用一個內部鎖保護這個兩個整數和mutex,讀寫操作互斥,寫寫操作互斥,讀讀操作不互斥。
type RWMutex struct {
mu sync.Mutex // 鎖定資源的鎖
lock sync.Mutex // 保護讀者數和寫者數的鎖
reader int
writer int
}
func (rwm *RWMutex) RLock() {
// 在寫鎖已被鎖定的情況下試圖鎖定讀鎖,會阻塞當前的goroutine
WAIT:
for rwm.writer > 0 {
time.Sleep(time.Millisecond * 1)
}
rwm.lock.Lock()
// double check
if rwm.writer > 0 {
rwm.lock.Unlock()
goto WAIT
}
// 在讀鎖已被鎖定的情況下再試圖鎖定讀鎖,並不會阻塞當前的 goroutine
if rwm.reader > 0 {
rwm.reader++
rwm.lock.Unlock()
return
}
rwm.reader++
rwm.mu.Lock()
rwm.lock.Unlock()
}
func (rwm *RWMutex) RUnlock() {
rwm.lock.Lock()
if rwm.reader > 1 {
rwm.reader--
rwm.lock.Unlock()
return
}
rwm.reader--
rwm.mu.Unlock()
rwm.lock.Unlock()
}
func (rwm *RWMutex) WLock() {
// 在寫鎖已被鎖定的情況下再試圖鎖定寫鎖,會阻塞當前的 goroutine。
// 在讀鎖已被鎖定的情況下試圖鎖定寫鎖,同樣會阻塞當前的 goroutine。
WAIT:
for rwm.reader > 0 || rwm.writer > 0 {
time.Sleep(time.Millisecond * 1)
}
rwm.lock.Lock()
// double check
if rwm.reader > 0 || rwm.writer > 0{
rwm.lock.Unlock()
goto WAIT
}
rwm.writer++
rwm.mu.Lock()
rwm.lock.Unlock()
}
func (rwm *RWMutex) WUnlock() {
rwm.lock.Lock()
rwm.writer--
rwm.mu.Unlock()
rwm.lock.Unlock()
}