mutex
同步锁
当一个 Goroutine(协程)获得了 Mutex 后,其他 Goroutine(协程)就只能乖乖的等待,除非该 Goroutine 释放了该 Mutex。RWMutex 在读锁占用的情况下,会阻止写,但不阻止读。RWMutex在写锁占用情况下,会阻止任何其他Goroutine(无论读和写)进来,整个锁相当于由该 Goroutine 独占同步锁的作用是保证资源在使用时的独有性,不会因为并发而导致数据错乱,保证系统的稳定性。
Mutex
四种状态
- Locked - 互斥锁锁定状态
- Woken - 是否有协程已被唤醒
- Starving - 是否处于饥饿状态
- Waiter - 表示等待锁的协程个数,协程解锁时根据此值来判断是否需要释放信号量
两种模式
- normal:正常模式,所有等待锁的goroutine按照FIFO顺序等待,唤醒的goroutine不会直接拥有锁,而是和新请求的goroutine竞争锁,新请求的goroutine更容易竞争到锁,因为它正在CPU上执行,所以刚刚唤醒的goroutine很大可能会竞争失败,这种情况下,会把刚刚唤醒的goroutine放到队列前面,而且加锁不成功会判断是否满足自旋条件,如果满足则会自动自旋,尝试抢锁。
- 饥饿模式 在饥饿模式下,会直接把锁交给队列第一位的goroutine,新进来的G也不会进入自旋状态而是放到队尾,当一个goroutine等待锁时间超过1ms时,或者当前队列只剩下一个goroutine时,Mutex切换到饥饿模式。
自旋条件
- 锁已经被占用了,并且锁不处于饥饿模式
- 积累的自选次数小于4次
- CPU核数大于1
- 有空闲的P
- 当前goroutine所挂载的P下,本地队列为空
实现原理
Barging
这种模式是为了提高吞吐量,当锁被释放时,它会唤醒第一个等待者,然后把锁给第一个等待者或者第一个请求锁的人
Handsoff
当锁被释放时候,锁会一直持有知道第一个等待者准备好获取锁。它降低了吞吐量,因为锁被持有,即使另一个goroutine准备获取它。平衡了锁分配,因为它会迫使第一个goroutine等待所。
Spinning
自旋在等待队列为空或者应用程序重度使用锁时效果不错,parking和unpariking goroutine有不低的性能成本开销,相比自旋来说慢得多。
mutex
https://www.zengzx.xyz/2022/07/08/01.知识架构/01.Go/01.基础/06.mutex/