目前正在阅读Go标准库的源码,该篇为读写锁源码解析,读这篇需要先读上一篇互斥锁源码解析,然后阅读这篇文章


读写锁结构

w 是一个互斥锁

writerSem 用于 写goroutine 等待正在进行的 读goroutine 释放信号量

readerSem 用于 读goroutine 等待正在进行的 写goroutine 释放信号量

readerCount 记录正在进行的 读goroutine 数量

readerWait 记录被阻塞的 读goroutine 数量


写锁

加锁

  1. 执行互斥锁加锁。
  2. 将readerCount 最高位置为1,也就是通知其他 读goroutine 有一个 写goroutine 获取了写锁。
  3. 获取有多少 读goroutine,并添加到waitNum中,方便读goroutine释放后通过信号量通知 写goroutine
  4. 等待这些读goroutine执行完,然后返回信号量。
  5. 获取信号量,则视为成功获取了锁。

解锁

  1. 将负数的readerCount变为正数,通知读goroutine已经没有写锁了
  2. 释放r个信号量,通知正在等待的r个读goroutine可以读了
  3. 执行互斥锁解锁


读锁

加锁

  1. readerCount + 1, 如果为正数,则获取锁成功
  2. 如果为负数,则说明有个写锁被获取,等待资源释放

解锁


  1. readerCount + -1 如果为正数,则解锁成功
  2. 如果为负数,则说明有一个写goroutine正在等待锁资源
  3. 执行unlockSlow,执行期间处理readerWait,当是最后一个读锁解锁得时候,通过信号量通知写锁可以获取资源了。