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,重新进入上面类似的循环
标签:lock,goroutine,sync,sema,golang,互斥,state,mutex,goroutine2 来源: https://blog.csdn.net/u014763610/article/details/114643667