加写锁的抢占

	// 在加写锁的时候通过将readerCount递减最大允许加读锁的数量,来实现对加读锁的抢占
	r := atomic.AddInt32(&rw.readerCount, -rwmutexMaxReaders) + rwmutexMaxReaders

  加读锁的抢占检测

// 如果没有写锁的情况下读锁的readerCount进行Add后一定是一个>0的数字,这里通过检测值为负数
//就实现了读锁对写锁抢占的检测
	if atomic.AddInt32(&rw.readerCount, 1) < 0 {
        // A writer is pending, wait for it.
        runtime_SemacquireMutex(&rw.readerSem, false)
    }

  写锁抢占读锁后后续的读锁就会加锁失败,但是如果想加写锁成功还要继续对已经加读锁成功的进行等待

if r != 0 && atomic.AddInt32(&rw.readerWait, r) != 0 {
    // 写锁发现需要等待的读锁释放的数量不为0,就自己自己去休眠了
    runtime_SemacquireMutex(&rw.writerSem, false)
}

  写锁既然休眠了,则必定要有一种唤醒机制其实就是每次释放锁的时候,当检查到有加写锁的情况下,就递减readerWait,并由最后一个释放reader lock的goroutine来实现唤醒写锁

if atomic.AddInt32(&rw.readerWait, -1) == 0 {
    // The last reader unblocks the writer.
    runtime_Semrelease(&rw.writerSem, false)
}