RWMutex

作者: wayyyy | 来源:发表于2022-04-05 00:56 被阅读0次

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

  • 写锁需要阻塞写锁:一个协程拥有写锁时,其他协程写锁定需要阻塞
  • 写锁需要阻塞读锁:一个协程拥有写锁时,其他协程读锁定需要阻塞
  • 读锁需要阻塞写锁:一个协程拥有读锁时,其他协程写锁定需要阻塞
  • 读锁不能阻塞读锁:一个协程拥有读锁时,其他协程也可以拥有读锁
读写锁数据数据结构

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

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

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

  • RLock 读锁定
  • RULock 解除读锁定
  • Lock 写锁定
  • Unlock 解除写锁定
Lock 实现逻辑

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

  1. 获取互斥锁
  2. 阻塞等待所有读操作结束
image.png
  • 写操作是如何阻止写操作?
    读写锁里面包含一个互斥锁w,写锁定必须先获取该互斥锁,如果互斥锁已经被协程A获取,则协程B只能阻塞等待该互斥锁。

  • 读操作如何阻止写操作?
    读锁定会先将readerCount的值加1(见下面),此时写操作到来时发现读者数量不为0,会阻塞等待所有读操作结束。

Unlock 实现逻辑

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

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

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

  1. 增加读操作计数
  2. 阻塞等待写操作计数
image.png
  • 写操作如何阻止读操作?
    readerCount 是一个整型值,用于表示读者数量,在不考虑写操作的情况下,每次读锁定将该值加1,每次解除锁定将该值减1,所以 readerCount 的取值为[0, N],N为读者个数,实际上最大可支持 2^30 个并发读者
    当进行写锁定时,会先将 readerCount 减去 2^30 ,从而 readerCount 变成了负值,此时再有读锁定到来时检测到为负值,便知道有写操作在进行,只好阻塞等待。
RUlock 实现逻辑

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

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

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

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

相关文章

  • golang 中 sync.Mutex 和 sync.RWMut

    介绍 golang 中的 sync 包实现了两种锁: Mutex:互斥锁 RWMutex:读写锁,RWMutex ...

  • golang笔记之基于共享变量的并发

    介绍 golang 中的 sync 包实现了两种锁: Mutex:互斥锁 RWMutex:读写锁,RWMutex ...

  • RWMutex

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

  • Go 语言的锁

    Go 语言提供两类锁: 互斥锁(Mutex)和读写锁(RWMutex)。其中读写锁(RWMutex)是基于互斥锁(...

  • go sync包的读写锁RWMutex的使用

    sync包的读写锁RWMutex的使用(sync.RWMutex) 我们使用“读写”锁的场景主要是在多线程的安全操...

  • go常用包——sync

    内容 Atomic Mutex RWMutex WaitGroup Once Sync.Map Sync.Pool...

  • 算法:读写者问题

    锁解析 : RWMutex : 读-写互斥锁 WWMutex : 写-写互斥锁 WPriorityMutex =...

  • rwmutex.go

    概述 rwmutex.go即读写锁,内部基于atomic和sync.mutex实现,提供四个方法 RLock 读锁...

  • go rwmutex 源码

  • Go语言之RWMutex

    转自“灰子学技术”,原文链接:https://mp.weixin.qq.com/s/0nfjNsFNIrMhYJM...

网友评论

      本文标题:RWMutex

      本文链接:https://www.haomeiwen.com/subject/ojcixrtx.html