目前正在阅读Go标准库的源码,该篇为读写锁源码解析,读这篇需要先读上一篇互斥锁源码解析,然后阅读这篇文章
读写锁结构
w 是一个互斥锁
writerSem 用于 写goroutine 等待正在进行的 读goroutine 释放信号量
readerSem 用于 读goroutine 等待正在进行的 写goroutine 释放信号量
readerCount 记录正在进行的 读goroutine 数量
readerWait 记录被阻塞的 读goroutine 数量
写锁
加锁
- 执行互斥锁加锁。
- 将readerCount 最高位置为1,也就是通知其他 读goroutine 有一个 写goroutine 获取了写锁。
- 获取有多少 读goroutine,并添加到waitNum中,方便读goroutine释放后通过信号量通知 写goroutine。
- 等待这些读goroutine执行完,然后返回信号量。
- 获取信号量,则视为成功获取了锁。
解锁
- 将负数的readerCount变为正数,通知读goroutine已经没有写锁了
- 释放r个信号量,通知正在等待的r个读goroutine可以读了
- 执行互斥锁解锁
读锁
加锁
- readerCount + 1, 如果为正数,则获取锁成功
- 如果为负数,则说明有个写锁被获取,等待资源释放
解锁
- readerCount + -1 如果为正数,则解锁成功
- 如果为负数,则说明有一个写goroutine正在等待锁资源
- 执行unlockSlow,执行期间处理readerWait,当是最后一个读锁解锁得时候,通过信号量通知写锁可以获取资源了。