源码分析 --golang 读写锁
发布于: 4 小时前
读写区别
读者:不需要修改数据
写者:读取和修改数据
问题约束
1.允许同一时间多个读者,任何时候只有一个写者
2 当没有写者时读者才能访问数据
3.当没有读者与写者时候写者才能访问数据
4.任何时候只有一个线程可以操作共享变量
源码分析
读写锁数据结构
type RWMutex struct {
w Mutex // 如果有待处理的写者,说明锁正在被获取
writerSem uint32 // 供写者等待完成读者的信号量
readerSem uint32 // 供读者等待完成写者的信号量
readerCount int32 // 处理中的读者数目
readerWait int32 // 要结束的读者数目
}
复制代码
读上锁操作
func (rw *RWMutex) RLock() {
if race.Enabled {
_ = rw.w.state
race.Disable()
}//race逻辑用于数据竞争检测,对读写锁的逻辑没有实际意义
if atomic.AddInt32(&rw.readerCount, 1) < 0 {
//如果待处理的readercount+1<0,说明获取读锁被阻塞,有写者在进行中
//写者获取锁的同时会将readercount的值设置成负数的最大可等待读者数目
//此时要等待写者完毕后的信号量
runtime_SemacquireMutex(&rw.readerSem, false, 0)
}
//否则就是获取读锁成功
if race.Enabled {
race.Enable()
race.Acquire(unsafe.Pointer(&rw.readerSem))
}
}
复制代码
读解锁操作
func (rw *RWMutex) RUnlock() {
if race.Enabled {
_ = rw.w.state
race.ReleaseMerge(unsafe.Pointer(&rw.writerSem))
race.Disable()
}
if r := atomic.AddInt32(&rw.readerCount, -1); r < 0 {
//r<0说明可能说多进行了一次解锁
rw.rUnlockSlow(r)
}
//如果r>=0说明解锁成功
if race.Enabled {
race.Enable()
}
}
func (rw *RWMutex) rUnlockSlow(r int32) {
if r+1 == 0 || r+1 == -rwmutexMaxReaders {
race.Enable()
//解锁了未锁的读锁
throw("sync: RUnlock of unlocked RWMutex")
}
// 有一个写者正在等待
if atomic.AddInt32(&rw.readerWait, -1) == 0 {
//最后一个读者解锁写者
runtime_Semrelease(&rw.writerSem, false, 1)
}
}
复制代码
锁操作
func (rw *RWMutex) Lock() {
if race.Enabled {
_ = rw.w.state
race.Disable()
}
// 首先和其他写者竞争锁
rw.w.Lock()
// 获取当前有多少在处理中的读者,并将读者的值设置成负数的最大等待数目,有新的读者就一直等待
r := atomic.AddInt32(&rw.readerCount, -rwmutexMaxReaders) + rwmutexMaxReaders
// 如果读者r为0,说明没有在运行的任务,可以直接锁定
// 如果r!=0,且readerwait + r !=0 代表还存在没有完全结束的读者,写者要等待读者信号
if r != 0 && atomic.AddInt32(&rw.readerWait, r) != 0 {
runtime_SemacquireMutex(&rw.writerSem, false, 0)
}
if race.Enabled {
race.Enable()
race.Acquire(unsafe.Pointer(&rw.readerSem))
race.Acquire(unsafe.Pointer(&rw.writerSem))
}
}
复制代码
解锁操作
func (rw *RWMutex) Unlock() {
if race.Enabled {
_ = rw.w.state
race.Release(unsafe.Pointer(&rw.readerSem))
race.Disable()
}
// Announce to readers there is no active writer.
r := atomic.AddInt32(&rw.readerCount, rwmutexMaxReaders)
if r >= rwmutexMaxReaders {
race.Enable()
throw("sync: Unlock of unlocked RWMutex")
}
//解锁所有等待中的读者
for i := 0; i < int(r); i++ {
runtime_Semrelease(&rw.readerSem, false, 0)
}
// Allow other writers to proceed.
rw.w.Unlock()
if race.Enabled {
race.Enable()
}
}
复制代码
划线
评论
复制
发布于: 4 小时前阅读数: 3
en
关注
还未添加个人签名 2018.06.14 加入
还未添加个人简介
评论