RWMutex

2022-04-05  本文已影响0人  wayyyy

前面分析了互斥锁,在针对写少读多的场景,更好的选择是使用读写锁。实现读写锁主要解决下列的问题:

读写锁数据数据结构

源码中定义了读写锁的数据结构:

type RWMutex struct {
    w           Mutex      //  用于控制多个写锁,获得写锁首先需要获取该锁
    writerSem   uint32     // 写阻塞等待的信号量,最后一个读者释放锁时会释放信号量
    readerSem   uint32     // 读阻塞的协程等待的信号量,持有写锁的协程释放锁后会释放信号量
    readerCount int32      // 记录读者的个数
    readerWait  int32      // 记录写阻塞时的读者个数
}

RWMutex 对外提供4个简单接口:

Lock 实现逻辑

写锁定操作需要做2件事:

  1. 获取互斥锁
  2. 阻塞等待所有读操作结束
image.png
Unlock 实现逻辑

解除写锁定需要做2件事:

  1. 唤醒因读锁定而被阻塞的协程
  2. 解除互斥锁,如果有其他协程写锁定操作,将被唤醒
image.png
RLock 实现逻辑

读锁定操作需要做2件事:

  1. 增加读操作计数
  2. 阻塞等待写操作计数
image.png
RUlock 实现逻辑

解除读锁定需要做2件事:

  1. 减少读操作计数
  2. 唤醒等待写操作的协程
image.png
为什么写锁定不会被饿死 ?

写操作要等待读操作结束后才可以获取到锁,写操作等待期间可能还有新的读操作持续到来,如果写操作要等所有读操作结束,则很可能会被饿死?那是怎么解决这个问题呢?

写操作到来时,会把readerCount的值复制到readerWait中,用于标记排在写操作前面的读者个数。
前面的读操作结束后,除了会递减readerCount的值,还会递减readerWait的值,当readerWait的值变为0时唤醒写操作,写操作结束后再唤醒后面的读操作。

上一篇 下一篇

猜你喜欢

热点阅读