本站消息

站长简介/公众号

  出租广告位,需要合作请联系站长

+关注
已关注

分类  

暂无分类

标签  

暂无标签

日期归档  

2024-11(1)

golang 源码分析05 Mutex

发布于2021-05-30 19:37     阅读(634)     评论(0)     点赞(29)     收藏(5)


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是需要在队尾排队的,就无法获取

 

 

 

 

 



所属网站分类: 技术文章 > 博客

作者:美丽的老婆你听我说

链接:http://www.phpheidong.com/blog/article/86837/9a931ae7bca01cd1268e/

来源:php黑洞网

任何形式的转载都请注明出处,如有侵权 一经发现 必将追究其法律责任

29 0
收藏该文
已收藏

评论内容:(最多支持255个字符)