小言_互联网的博客

golang 源码分析05 Mutex

317人阅读  评论(0)

state表示mutex的状态

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

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


  
  1. 互斥量可分为两种操作模式:正常和饥饿。
  2. 在正常模式下,等待的goroutines按照FIFO(先进先出)顺序排队,但是goroutine被唤醒之后并不能立即得到mutex锁,它需要与新到达的goroutine争夺mutex锁。
  3. 因为新到达的goroutine已经在CPU上运行了,所以被唤醒的goroutine很大概率是争夺mutex锁是失败的。出现这样的情况时候,被唤醒的goroutine需要排队在队列的前面。
  4. 如果被唤醒的goroutine有超过1ms没有获取到mutex锁,那么它就会变为饥饿模式。
  5. 在饥饿模式中,mutex锁直接从解锁的goroutine交给队列前面的goroutine。新达到的goroutine也不会去争夺mutex锁(即使没有锁,也不能去自旋),而是到等待队列尾部排队。
  6. 在饥饿模式下,有一个goroutine获取到mutex锁了,如果它满足下条件中的任意一个,mutex将会切换回去正常模式:
  7. 1. 是等待队列中的最后一个goroutine
  8. 2. 它的等待时间不超过1ms。
  9. 正常模式有更好的性能,因为goroutine可以连续多次获得mutex锁;
  10. 饥饿模式对于预防队列尾部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是需要在队尾排队的,就无法获取

 

 

 

 

 


转载:https://blog.csdn.net/kuaipao19950507/article/details/117228721
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场