GOのRWMutexに対する自分の理解について話します
RWMutexのコアはやはりMutexに基づいているので、Mutexを知りたいなら前に書いたMutexの文章を見てもいいです.
RWMutexの特性は同時読み取りをサポートすることである.読み書きが少ないシーンに適しています.
リードロックを取得するプロセス readerCount + 1 readerCount<0で、書き込みロックによってブロックされているか否かを判断する、そうすると、現在goroutineは休眠 に入る.
リードロックを解除するプロセス readerCount - 1 はreaderCount<0で書き込みロック があるか否かを判断する.書き込みロックがない場合は、 に戻ります.書き込みロックがあればrUnlockSlowメソッドを呼び出し、readerWait-1 readerWait==0の場合、現在のgoroutineが書き込みロック待ちの最後の読み取りロックgoroutineであることを示し、書き込みロックgoroutine を起動する必要がある
書き込みロックの取得プロセスまず反発ロック を取得する. readerCount-rwmutexMaxReaders、後続の読み取り操作はすべて をブロックします. readerWait+=readerCountは、現在実行中の読み取り操作の数をreaderWait上の に加算する readerWait!=0は、現在他のgoroutineがリードロックを持っていることを示し、現在goroutineは睡眠に入り、目覚ましを待つ 書き込みロックプロセスの解放 readerCount+rwmutexMaxReaders、後続のリードロックは をブロックしません. readerCountは、以前に書き込みロックによってブロックされたリードロックgoroutine個数を表し、readerCount個のリードロックgoroutine を起動する.最後に反発ロック を解放する.
最後に
RWMutexはMutexに対してリードロックの制御を増やし、コードロジックの複雑さについては、RWMutexはMutexよりもずっと簡単で、Mutexの流れに慣れていれば、すぐにRWMutexの原理を把握することができます
RWMutexの特性は同時読み取りをサポートすることである.読み書きが少ないシーンに適しています.
RWMutexの定義
type RWMutex struct {
w Mutex //
writerSem uint32 //
readerSem uint32 //
readerCount int32 // goroutine
readerWait int32 // , goroutine
}
const rwmutexMaxReaders = 1 << 30
RWMutex.Lock()
func (rw *RWMutex) Lock() {
// Mutex Lock
rw.w.Lock()
// readerCount ,
// r goroutine
r := atomic.AddInt32(&rw.readerCount, -rwmutexMaxReaders) + rwmutexMaxReaders
// goroutine
// r readerWait
if r != 0 && atomic.AddInt32(&rw.readerWait, r) != 0 {
// goroutine ,
runtime_SemacquireMutex(&rw.writerSem, false, 0)
}
}
RWMutex.Unlock()
func (rw *RWMutex) Unlock() {
// readerCount ,
r := atomic.AddInt32(&rw.readerCount, rwmutexMaxReaders)
...
// goroutine
for i := 0; i < int(r); i++ {
runtime_Semrelease(&rw.readerSem, false, 0)
}
// ,
rw.w.Unlock()
}
RWMutex.RLock()
func (rw *RWMutex) RLock() {
...
// readerCount + 1
if atomic.AddInt32(&rw.readerCount, 1) < 0 {
// 0, goroutine , goroutine
runtime_SemacquireMutex(&rw.readerSem, false, 0)
}
...
}
RWMutex.RUnlock()
func (rw *RWMutex) RUnlock() {
...
// readerCount - 1
// readerCount < 0, gouroutine , goroutine
// readerCount >= 0, ,
if r := atomic.AddInt32(&rw.readerCount, -1); r < 0 {
//
rw.rUnlockSlow(r)
}
...
}
func (rw *RWMutex) rUnlockSlow(r int32) {
...
// readerWait - 1
// goroutine
if atomic.AddInt32(&rw.readerWait, -1) == 0 {
//
runtime_Semrelease(&rw.writerSem, false, 1)
}
}
まとめ
リードロックを取得するプロセス
リードロックを解除するプロセス
書き込みロックの取得プロセス
最後に
RWMutexはMutexに対してリードロックの制御を増やし、コードロジックの複雑さについては、RWMutexはMutexよりもずっと簡単で、Mutexの流れに慣れていれば、すぐにRWMutexの原理を把握することができます