公平锁:
锁有两种模式:正常模式、饥饿模式
- 正常模式下,维护一个先进先出的goroutine的等待队列,并且唤醒的goroutine需要和新的goroutine一起竞争,容易发送锁饥饿。
- 饥饿模式下,锁的所有权从锁的释放直接给到等待队列的头部,不参与任何竞争。
- 正常模式性能比饥饿模式高,因为一个goroutine有多次机会触发获取锁;饥饿模式防止尾部延迟。
- 正常模式->饥饿模式条件:1:某个goroutine等待锁时间超过1ms。
- 饥饿模式->正常模式条件:1:它是等待队列的最后一个;2. 它拿到锁的时间小于1ms。
- mutexWaiterShift int32常量一直累加,代表等待gorountine的数量,超过类型进度,大概3亿个goroutine会溢出。
- 使用cas更新状态。
自旋拿锁:
- 饥饿模式不自旋。
- 加锁,并且符合能够自旋的逻辑。
- 先设置锁的状态和再修改自身的状态。
- 自旋的条件:1: 自旋的次数小于active_count=4,2: 当前允许环境是多核机器,3: 当前P没有等待任务;4. 存在另外运行的P。
解锁
- 锁和goroutine没有绑定关系,允许加锁和解锁的不再同一个goroutine。