源码分析 --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 加入
还未添加个人简介











评论