golang 源码分析05 Mutex

state表示mutex的状态

上图是Mutex的结构体和locker接口方法定义

Mutex的公平性,两种操作模式 正常normal和饥饿starvation

互斥量可分为两种操作模式:正常和饥饿。

在正常模式下,等待的goroutines按照FIFO(先进先出)顺序排队,但是goroutine被唤醒之后并不能立即得到mutex锁,它需要与新到达的goroutine争夺mutex锁。

因为新到达的goroutine已经在CPU上运行了,所以被唤醒的goroutine很大概率是争夺mutex锁是失败的。出现这样的情况时候,被唤醒的goroutine需要排队在队列的前面。

如果被唤醒的goroutine有超过1ms没有获取到mutex锁,那么它就会变为饥饿模式。

在饥饿模式中,mutex锁直接从解锁的goroutine交给队列前面的goroutine。新达到的goroutine也不会去争夺mutex锁(即使没有锁,也不能去自旋),而是到等待队列尾部排队。

在饥饿模式下,有一个goroutine获取到mutex锁了,如果它满足下条件中的任意一个,mutex将会切换回去正常模式:

1. 是等待队列中的最后一个goroutine

2. 它的等待时间不超过1ms。

正常模式有更好的性能,因为goroutine可以连续多次获得mutex锁;

饥饿模式对于预防队列尾部goroutine一致无法获取mutex锁的问题。

下面看下核心方法lock

1.如果当前state为0,代表这个锁没有被持有,所以就通过CAS来获取锁,这个也是快速获取锁的路径

2.如果当前state不为0,那么就进行lockSlow流程

3.判断,如果是饥饿starvation模式,就不自旋,新到达的goroutine必须排队;如果是normal正常模式,就进入自旋,尝试获取锁

4.goroutine已经从sleep中唤醒,所以我们需要重置flag

 

6.获取锁成功,就直接break,如果之前已经等待过,就在queue的开头排队

 

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

下面再来看unlock释放锁

1.如果没有lock,直接就unlock,那么就会出现一个run-time 错误

2.一个锁住的mutex,不会专属于一个指定的goroutine;通常是一个goroutine锁住mutex,另一个goroutine争抢,来解锁unlock

3.快速解锁,就是state - mutexLocked,如果不为0,就调用unlockSlow解锁

4.如果没有waiters,或者1个goroutine已经被唤醒,并且抢到了锁,就没有必要唤醒其余的goroutine了

5.如果是饥饿模式,那么就直接解锁下一个waiter,新来的goroutine是需要在队尾排队的,就无法获取

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值