当前位置: 移动技术网 > IT编程>脚本编程>Go语言 > 详解golang RWMutex读写互斥锁源码分析

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

2018年08月06日  | 移动技术网IT编程  | 我要评论

针对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实现

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

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网