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
// 每调用RLock()一次readerCount就会自增1
readerCount int32 // number of pending readers
// 当调用Lock()时即进入加写锁状态,此时会把readerCount里正在读的数量加到readerWait
readerWait int32 // number of departing readers
}
// 加读锁, 判断readerCount加1后是不是小于0,如果小于0说明Lock()把readerCount减了一个很大的负数,也就是说进入了获取写锁状态,
// 此时判断readerCount小于0, RLock()只能进入阻塞等待状态。如果大于0,表示没有写锁进入,则直接获得读锁
,func (rw *RWMutex) RLock() {
if atomic.AddInt32(&rw.readerCount, 1) < 0 {
// A writer is pending, wait for it.
runtime_SemacquireMutex(&rw.readerSem, false, 0)
}
}
// 释放读锁, 如果readerCount减1小于0,说明有写锁在等待,即有调用Lock()导致readerCount是一个很大的负数,此时释放读锁就要把readerWait减1
// 等readerWait减到0时即表示所有的读锁都释放了,可以唤醒写锁了。如果readerCount减1不小于0,则说明没有写锁在等待,可通过readerCount减1直接释放读锁
func (rw *RWMutex) RUnlock() {
if r := atomic.AddInt32(&rw.readerCount, -1); r < 0 {
// Outlined slow-path to allow the fast-path to be inlined
rw.rUnlockSlow(r)
}
}
func (rw *RWMutex) rUnlockSlow(r int32) {
// A writer is pending.
if atomic.AddInt32(&rw.readerWait, -1) == 0 {
// The last reader unblocks the writer.
runtime_Semrelease(&rw.writerSem, false, 1)
}
}
// 加写锁, 直接调用互斥锁,解决跟其它写者锁的竞争,假如获取了互斥锁,则把readerCount加上一个很大的负数使其进入写锁获取状态阻止后来的读者获取读锁,
// 同时判断readerCount还有多少读者没有释放锁,如果有读者数量大于0,则把读者数据加到readerWait上等待读者释放读锁,同时写者进入阻塞等待状态,如果小于等于0则直接获得写锁
func (rw *RWMutex) Lock() {
// First, resolve competition with other writers.
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_SemacquireMutex(&rw.writerSem, false, 0)
}
}
// 释放写锁,把readerCount加回一个很大正数,此时判断readerCount是否大于0,如果大于表示在释放写锁之前已经有读者在等待写者释放写锁从面获得读锁了,
// 此时需要一个一个地唤醒阻塞等待的读者。最后释放互斥锁
func (rw *RWMutex) Unlock() {
// Announce to readers there is no active writer.
r := atomic.AddInt32(&rw.readerCount, rwmutexMaxReaders)
// Unblock blocked readers, if any.
for i := 0; i < int(r); i++ {
runtime_Semrelease(&rw.readerSem, false, 0)
}
// Allow other writers to proceed.
rw.w.Unlock()
}