Mutex
|
|
state 通过位掩码管理锁的多种状态:
- 位偏移为 0: 锁是否被持有(1 表示锁定,0 表示未锁定)
- 位偏移为 1: 是否有被唤醒的 goroutine
- 位偏移为 2: 是否处于饥饿状态
- 位偏移为 3-31: 等待锁的 goroutine 数量
sync.Mutex 有两种工作模式:
- 正常模式
- 等待者按先进先出顺粗获取锁,但新的请求会尝试直接获取锁
- 新请求锁的 goroutine 可能会“插队”,以提高吞吐量
- 饥饿模式
- 当某个等待者的等待时间超过 1ms 时,会切换到饥饿模式,防止部分 goroutine 长时间等待
- 新请求的 goroutine 进入等待队列尾部,不在尝试竞争所
- 锁释放时直接交给等待队列头部的 goroutine
- 等待队列为空,或等待者等待时间少于 1ms 时,切换回正常模式
Lock
- 快速路径
- 通过 atomic.CompareAndSwapInt32 原子操作尝试直接获取锁
- 慢路径
- 进行有限次的自旋,尝试抢占锁
- 更新等待者计数,挂起 goroutine,并将其加入等待队列,直到被唤醒
Unlock
- 快速路径
- 通过 atomic.CompareAndSwapInt32 原子操作尝试释放锁
- 慢路径
- 根据模式唤醒等待者
- 正常模式:优先唤醒新请求的 goroutine
- 饥饿模式:直接将锁交给队列头部的等待者
- 根据模式唤醒等待者
RWMutex
|
|
略
Once
|
|
sync.Once.Do 是对外暴露的唯一方法:
|
|
Once 通过原子操作和互斥锁来保证函数只执行一次:
- 原子操作检查 done 是否为 0
- 如果是 0,获取锁,并将 done 设置为 1