mutexLocked = 1 << iota // mutex is locked
mutexWoken
mutexStarving
mutexWaiterShift = iota
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(当写者要进行写是,当前还必须等待多少个读者读完)
}
func (rw *RWMutex) Lock() {
...
// First, resolve competition with other writers.
//读者要进行读,所以将readerCount减去rwmutexMaxReaders(1<<30),然后计算当前还有
//多少读者在读,写入到readerWait中,然后求获取写的信号量从而阻塞;
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)
}
...
}
func (rw *RWMutex) RLock() {
....
//读者尝试获取,readerCount+1
//如果小于0,说明前面有写者打算写(被减去rwmutexMaxReaders)
//所以新来的读者会被阻塞,获取读者信号量从而阻塞;
//大于0就不需要额外操作
if atomic.AddInt32(&rw.readerCount, 1) < 0 {
// A writer is pending, wait for it.
runtime_SemacquireMutex(&rw.readerSem, false)
}
...
}
func (rw *RWMutex) RUnlock() {
....
//先将读者总数-1,然后判断是否小于0;
//同样,小于0表示有写者要准备写了,所以需要在进一步判断
//readerWait是否为0,为0说明之前写申请的时候还在读的读者都读完了,可以写了,释放读的信号,唤醒写瞎线程
//大于0同样不操作
if r := atomic.AddInt32(&rw.readerCount, -1); r < 0 {
if r+1 == 0 || r+1 == -rwmutexMaxReaders {
race.Enable()
throw("sync: RUnlock of unlocked RWMutex")
}
// A writer is pending.
if atomic.AddInt32(&rw.readerWait, -1) == 0 {
// The last reader unblocks the writer.
runtime_Semrelease(&rw.writerSem, false)
}
}
....
}
func (rw *RWMutex) Unlock() {
....
// Announce to readers there is no active writer.
//写锁解锁,将readerCount加回rwmutexMaxReaders,
//然后判断是否对没上锁的锁解锁
//由于在写过程中是不会有其他读者的,所以当前有的读者都在阻塞
//所以直接循环r次,将读的信号量加回来并唤醒读线程
r := atomic.AddInt32(&rw.readerCount, rwmutexMaxReaders)
if r >= rwmutexMaxReaders {
race.Enable()
throw("sync: Unlock of unlocked RWMutex")
}
// Unblock blocked readers, if any.
for i := 0; i < int(r); i++ {
runtime_Semrelease(&rw.readerSem, false)
}
// Allow other writers to proceed.
rw.w.Unlock()
....
}