sync mutex golang

互斥锁Mutex实现:

参考代码分析:https://www.jianshu.com/p/ce1553cc5b4f

大致介绍

sema 是一个互斥的信号量,初始默认值是 0,用于将 goroutine park 休眠或是唤醒。sema acquire 时如果 sema 大于 0,那么减一返回,否则休眠等待。sema release 将 sema 加一,然后唤醒等待队列的第一个 goroutine

sema为非零值
Sem acquire Mutex: 大于 0,那么减一返回,否则休眠等待
Sem release: 将sema加一,然后唤醒等待队列的第一个goroutine

state 存贮锁当前的状态

锁开发历程:

粗粒度 -> 添加自旋 -> 添加饥饿状态

添加自旋:解决切换goroutine状态的问题,goroutine都要休眠 park, 徒增 runtime 调度的开销
spin就是cpu空跑,对应汇编代码里面的pause

添加饥饿状态:新加了starving状态,如果当前处于starving状态,新进来的goroutine是获取不到lock的,直接加入
等待队列(先进先出FIFO)
退出饥饿状态的条件:当前 Goroutine 是互斥锁上的最后一个等待的协程或者等待的时间小于 1ms,那么它会将互斥锁切换回正常模式

场景

按照场景去理解代码,更加好理解
场景1:
第一步上锁:只是修改state为1
直接解锁:直接state减1

场景2:
第一步goroutine1上锁,state修改为1

又来一个goroutine2来lock,waiter增加一个
sema默认值为0,semacquire阻塞,(sema-1是否小于0,如果小于0,则挂住)

这时goroutine1解锁,调用semrelease,sema加一,state变为0,waiter减一

goroutine2 semacquire阻塞解开,sema减1
awoke设置为true,重新进入循环,此时state为0,直接break掉,设置状态为new,goroutine2 lock住

场景3:
第一步goroutine1上锁,state修改为1

又来一个goroutine2来lock,waiter增加一个
sema默认值为0,semacquire阻塞

这时goroutine1解锁,调用semrelease,sema加一,state变为0,waiter减一
goroutine2 semacquire阻塞解开,sema减1
awoke设置为true,重新进入循环,此时state为0,sema为0

此时goroutine3进来lock,此state变为1,goroutine3获得锁,返回
goroutine2,重新进入循环,awoke为true,重新进入上面类似的循环

RLock

RWMutex实现,使用Mutex实现

场景一:
goroutine1调用Lock,wlock住,其它write lock进不了,然后将readerCount减去rwmutexMaxReaders
Lock
// r := atomic.AddInt32(&rw.readerCount, -rwmutexMaxReaders) + rwmutexMaxReaders
RLock
// r := atomic.AddInt32(&rw.readerCount, -1); r < 0
case 1:Lock先执行,这是rw.readerCount为-rwmutexMaxReaders,RLock执行到atomic.AddInt32(&rw.readerCount, 1)为复数,进入runtime_SemacquireMutex(&rw.readerSem, false, 0),挂住
case 2:Unlock先执行,readerCount为1,执行到r := atomic.AddInt32(&rw.readerCount, -rwmutexMaxReaders) + rwmutexMaxReaders,r为1,执行runtime_SemacquireMutex(&rw.writerSem, false, 0)挂住

释放锁
case1:执行Unlock,r := atomic.AddInt32(&rw.readerCount, rwmutexMaxReaders),获取到当前阻塞的Rlock个数
依次释放,read lock可以多次进入(此时w未解锁,Lock进不去),这时RLock执行完
for i := 0; i < int®; i++ {
runtime_Semrelease(&rw.readerSem, false, 0)
}
最后释放w Unlock

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值