ラフでシンプルなアイデアは、ミューテックスをリソースロックとして使用し、2つの整数を使用してリーダーとライターの数を記録し、内部ロックを使用して2つの整数とミューテックスを保護することです。読み取りと書き込みの操作は相互に排他的です。と書き込み操作は相互に排他的ですが、読み取り読み取り操作は相互に排他的ではありません。
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()
}