针对Golang 1.9的sync.RWMutex进行分析,与Golang 1.10基本一样除了将panic改为了throw之外其他的都一样。
RWMutex是读写互斥锁。锁可以由任意数量的读取器或单个写入器来保持。 RWMutex的零值是一个解锁的互斥锁。
以下代码均去除race竞态检测代码

源代码位置:sync\rwmutex.go

结构体

type RWMutex struct {w           Mutex  // 互斥锁writerSem   uint32 // 写锁信号量readerSem   uint32 // 读锁信号量readerCount int32  // 读锁计数器readerWait  int32  // 获取写锁时需要等待的读锁释放数量
}
复制代码

常量

const rwmutexMaxReaders = 1 << 30   // 支持最多2^30个读锁
复制代码

方法

Lock

提供写锁操作.

func (rw *RWMutex) Lock() {// 竞态检测if race.Enabled {_ = rw.w.staterace.Disable()}// 使用Mutex锁rw.w.Lock()// Announce to readers there is a pending writer.r := atomic.AddInt32(&rw.readerCount, -rwmutexMaxReaders) + rwmutexMaxReaders// Wait for active readers.if r != 0 && atomic.AddInt32(&rw.readerWait, r) != 0 {runtime_Semacquire(&rw.writerSem)}// 竞态检测if race.Enabled {race.Enable()race.Acquire(unsafe.Pointer(&rw.readerSem))race.Acquire(unsafe.Pointer(&rw.writerSem))}
}
复制代码

RLock

提供读锁操作,

func (rw *RWMutex) RLock() {// 竞态检测if race.Enabled {_ = rw.w.staterace.Disable()}// 每次goroutine获取读锁时,readerCount+1// 如果写锁已经被获取,那么readerCount在-rwmutexMaxReaders与0之间,这时挂起获取读锁的goroutine,// 如果写锁没有被获取,那么readerCount>0,获取读锁,不阻塞// 通过readerCount判断读锁与写锁互斥,如果有写锁存在就挂起goroutine,多个读锁可以并行if atomic.AddInt32(&rw.readerCount, 1) < 0 {// 将goroutine排到G队列的后面,挂起goroutineruntime_Semacquire(&rw.readerSem)}// 竞态检测if race.Enabled {race.Enable()race.Acquire(unsafe.Pointer(&rw.readerSem))}
}
复制代码

RLocker

可以看到RWMutex实现接口Locker.

type Locker interface {Lock()Unlock()
}
复制代码

而方法RLocker就是将RWMutex转换为Locker.

func (rw *RWMutex) RLocker() Locker {return (*rlocker)(rw)
}
复制代码

总结

读写互斥锁的实现比较有技巧性一些,需要几点

  1. 读锁不能阻塞读锁,引入readerCount实现

  2. 读锁需要阻塞写锁,直到所以读锁都释放,引入readerSem实现

  3. 写锁需要阻塞读锁,直到所以写锁都释放,引入wirterSem实现

  4. 写锁需要阻塞写锁,引入Metux实现

golang RWMutex读写互斥锁源码分析相关推荐

  1. Linux线程同步(三)---互斥锁源码分析

    先给自己打个广告,本人的微信公众号:嵌入式Linux江湖,主要关注嵌入式软件开发,股票基金定投,足球等等,希望大家多多关注,有问题可以直接留言给我,一定尽心尽力回答大家的问题. 一 源码分析 1.li ...

  2. Ceph 学习——OSD读写流程与源码分析(一)

    消息从客户端发送而来,之前几节介绍了 客户端下 对象存储.块存储库的实现以及他们在客户端下API请求的发送过程(Ceph学习--Librados与Osdc实现源码解析 . Ceph学习--客户端读写操 ...

  3. Golang日志框架lumberjack包源码分析

    github地址:  https://github.com/natefinch/lumberjack 获取源码 go get gopkg.in/natefinch/lumberjack.v2 介绍 l ...

  4. Golang|区块链UTXO集源码分析

    区块链UTXO集源码分析 资源 go实现区块链 前提 在未实现UTXO集之前,假设系统需要查询某个钱包地址的余额,系统需要遍历区块链的所有区块,当区块链非常长时,这种做法的成本太高了. UTXO集是未 ...

  5. 基于后端开发Redisson实现分布式锁源码分析解读

    一.分布式锁的概念和使用场景 分布式锁是控制分布式系统之间同步访问共享资源的一种方式. 在分布式系统中,常常需要协调他们的动作.如果不同的系统或是同一个系统的不同主机之间共享了一个或一组资源,那么访问 ...

  6. golang学习之negroni/gizp源码分析

    在 Go 语言里,Negroni 是一个很地道的 Web 中间件,它是一个具备微型.非嵌入式.鼓励使用原生 net/http 库特征的中间件.利用它地Use功能,我们可以很简单地自定义中间件并使用.其 ...

  7. java锁源码分析-1获取锁的过程

    这篇文章(包括后边两篇)是六月份写的,写完后由于工作较忙,草稿一致没时间修改,今天偶尔翻到,担心哪天弄丢了,于是先以草稿的形式发布,内容有瑕疵,等以后有时间再修复. 解读类的结构 首先来看类的继承关系 ...

  8. golang 1.10 mutex互斥锁源码

    Mutex锁分为normal模式和starvation模式.一开始默认处于normal模式.在normal模式中,每个新加入竞争锁行列的协程都会直接参与到锁的竞争当中来,而处于starvation模式 ...

  9. ReentrantLock之公平锁源码分析

    本文分析的ReentrantLock所对应的Java版本为JDK8. 在阅读本文前,读者应该知道什么是CAS.自旋. 本文大纲 1.ReentrantLock公平锁简介 2.AQS 3.lock方法 ...

最新文章

  1. 深度学习最新方法:随机加权平均,击败了当前最先进的Snapshot Ensembling
  2. Android XML 不常用属性
  3. nginx优化25条
  4. Ubuntu16.04下面的vs code出现Unable to activate CppCheck analyzer
  5. 数据库事务及隔离级别
  6. C++ 函数重载碰到默认的参数
  7. 计算机软件理论基础集合论,从数理逻辑观点看计算机专业的理论基础探讨
  8. Ajax开发框架(上)[整理]
  9. 剑指offer(C++)-JZ8:二叉树的下一个结点(数据结构-树)
  10. Nginx源码分析 - Event事件篇 - Event模块的进程初始化(18)
  11. 华三交换机配置access命令_华三交换机配置中,shutdown这条命令怎么用?
  12. 基于GIS的中国历代名人人生轨迹研究
  13. welearn综合教程网课答案
  14. 算是我看源码时的一个小技巧吧~
  15. python中图形绘制技术的应用_python数据图形化—— matplotlib 基础应用
  16. pytorch锁死在dataloader(训练时卡死)
  17. 智能音箱大战全面开火,那么问题来了:如何成为一名全栈语音识别工程师?
  18. ArcGIS中无法复制粘贴的问题
  19. ArcGIS官方帮助文档和教程整理
  20. 2.5 矩阵因式分解(第2章矩阵代数)

热门文章

  1. 【学习笔记】WAMP
  2. Zend Framework 入门(1)—快速上手
  3. 影响机器视觉检测系统不稳定性因素分析
  4. Promise 必知必会(十道题)
  5. linux   find acm time
  6. MySQL索引类型详解,让MySQL高效运行起来
  7. 存储分析:RAID技术走向何方?
  8. 万能Ghost全攻略(最详细完整的教程)
  9. 输入字符数字串输出保存数字串
  10. native层 安卓_安卓逆向学习入门之过反调试(一)