• 企业400电话
  • 微网小程序
  • AI电话机器人
  • 电商代运营
  • 全 部 栏 目

    企业400电话 网络优化推广 AI电话机器人 呼叫中心 网站建设 商标✡知产 微网小程序 电商运营 彩铃•短信 增值拓展业务
    详解golang RWMutex读写互斥锁源码分析

    针对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.state
     race.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.state
     race.Disable()
     }
     // 每次goroutine获取读锁时,readerCount+1
      // 如果写锁已经被获取,那么readerCount在-rwmutexMaxReaders与0之间,这时挂起获取读锁的goroutine,
      // 如果写锁没有被获取,那么readerCount>0,获取读锁,不阻塞
      // 通过readerCount判断读锁与写锁互斥,如果有写锁存在就挂起goroutine,多个读锁可以并行
     if atomic.AddInt32(rw.readerCount, 1)  0 {
     // 将goroutine排到G队列的后面,挂起goroutine
     runtime_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实现

    以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

    您可能感兴趣的文章:
    • GO语言并发编程之互斥锁、读写锁详解
    • 详解Golang互斥锁内部实现
    • Go语言实现互斥锁、随机数、time、List
    上一篇:go语言中排序sort的使用方法示例
    下一篇:go语言学习之包和变量详解
  • 相关文章
  • 

    © 2016-2020 巨人网络通讯 版权所有

    《增值电信业务经营许可证》 苏ICP备15040257号-8

    详解golang RWMutex读写互斥锁源码分析 详解,golang,RWMutex,读写,互斥,