首页 > 编程语言 >go RWMutex源码分析

go RWMutex源码分析

时间:2023-01-21 19:44:20浏览次数:47  
标签:rw RWMutex writer 源码 atomic reader go readerCount

适用场景

并发场景下读多写少。

字段含义

RWMutex基于Mutex,写优先,Lock函数(反转readerCount)会阻止新的reader获取锁。

type RWMutex struct { 
  w Mutex   // writer之间互斥 
  writerSem  uint32  // writer信号量 
  readerSem  uint32  // reader信号量 
  readerCount int32   // reader数量 
  readerWait int32   // writer等待reader的数量 
} 
// reader最大数量
const rwmutexMaxReaders = 1 << 30

RLock

func (rw *RWMutex) RLock() { 
    // 如果readerCount是负值,那么有writer请求锁时,阻塞后来的reader
    if atomic.AddInt32(&rw.readerCount, 1) < 0 {  
        runtime_SemacquireMutex(&rw.readerSem, false, 0) 
    }
}

RUnlock

func (rw *RWMutex) RUnlock() { 
    if r := atomic.AddInt32(&rw.readerCount, -1); r < 0 {
        // 有等待的writer
        rw.rUnlockSlow(r) 
    } 
}

func (rw *RWMutex) rUnlockSlow(r int32) {
   // 最后一个reader释放锁后唤醒writer
  if atomic.AddInt32(&rw.readerWait, -1) == 0 {
      runtime_Semrelease(&rw.writerSem, false, 1) 
  } 
}

Lock

func (rw *RWMutex) Lock() {
    rw.w.Lock()
    // 反转readerCount,告诉reader有writer竞争锁,阻塞后面的reader
    // readerCount = readerWait(writer前面的读者数量)+writer后面的读者数量
    r := atomic.AddInt32(&rw.readerCount, -rwmutexMaxReaders) + rwmutexMaxReaders 
    // 如果当前有reader持有锁,那么等待前面的reader释放锁
    if r != 0 && atomic.AddInt32(&rw.readerWait, r) != 0 { 
        runtime_SemacquireMutex(&rw.writerSem, false, 0) 
    } 
} 

Unlock

func (rw *RWMutex) Unlock() { 
    // 反转readerCount,新来的reader可以直接获取到读锁
    r := atomic.AddInt32(&rw.readerCount, rwmutexMaxReaders) 

    // 唤醒writer后所有reader
    for i := 0; i < int(r); i++ { 
        runtime_Semrelease(&rw.readerSem, false, 0) 
    }

    rw.w.Unlock() 
}

 

标签:rw,RWMutex,writer,源码,atomic,reader,go,readerCount
From: https://www.cnblogs.com/WJQ2017/p/17063995.html

相关文章

  • 【算法-基础之排序01】Go语言实现
    仓库码云地址远程仓库地址声明本人是个菜鸟,不一定对哦。。。我只测试一个是正确的。还有对于数组只有一个数或者nil的不考虑。先写一个公共的方法。替换俩个位置的数......
  • go sync.Once源码分析
    适用场景服务启动时读取全局配置。单个函数流程里面只调用一次。源码双重检查done值是0后,加锁执行指定函数并把done值改成1。typeOncestruct{ doneuint32 mM......
  • GO语言之环境搭建和基本命令
    目录go语言基础下载go编译器go目录简介gopath简介环境变量配置GOPATHPATHgo语言项目结构IDE下载与配置安装golandgoland里添加goroot和gopath编写第一个GO程序编译go文件在......
  • 一文学会 Go 的三个主流开发框架
    一文学会Go的三个主流开发框架前言本文介绍了三个Go主流开发框架GORM,Kitex,Hertz的基本使用方法,覆盖了ORM,RPC,HTTP三个领域。帮助读者快速入门Go工程开发。GORM......
  • alpha shape algorithm
    一个求轮廓的算法analphavalue(0<α<∞)isaparameterimposingtheprecisionofthefinalboundary.Alargevalue(α->∞)resultsinthealphaboundaryo......
  • (17)go-micro微服务Prometheus监控
    目录一Prometheus监控介绍1.微服务监控系统promethues介绍2.微服务监控系统promethues工作流程二Prometheus监控重要组件和重要概念1.微服务监控系统promethues重要组件2......
  • golang字典生成算法实现(全排列实现)
    packagemain//@Title main.go//@Description 入口文件//@Author xiao//@Update noneimport( "flag" "fmt" "log")//字典常量const( lowerCaseChar......
  • MongoDB cmd CRUD操作 对照SQL
    问题​​参考官方文档​​使用MogoDB你就要熟悉他的常用cmd命令,增删改查,聚合多表查询等基本操作,本片博客旨在教会大家快速上手MogoDB,对其有基本了解,会对照Oracle的SQL查询......
  • Google 的新玩法 Fact Check
    美国总统大选期间,希拉里和川普在一本正经胡说八道的同时,媒体们和吃瓜群众也在忙着用factcheck(事实查证)给政客们打脸。昨天,Google奉献神助攻,他们给GoogleNews增加......
  • GoodBye Renyin ABC题解
    GoodByeRenyinABC题解A答案为\(\text{YES}\)的充要条件是\(\max(a_i)\timesr\le(\suma_i-\max(a_i))\timesR\)。必要性显然。充分性是可以先把最大的放在\((......