写点什么

源码分析 --golang 读写锁

用户头像
en
关注
发布于: 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() }}
复制代码


用户头像

en

关注

还未添加个人签名 2018.06.14 加入

还未添加个人简介

评论

发布
暂无评论
源码分析--golang读写锁