返回归档
🔒Golang

golang的单机锁

文章目录

正常模式

两种策略

  • 阻塞/唤醒:将当前goroutine阻塞挂起,直到锁被释放后,以回调的方式将阻塞goroutine重新唤醒,进行锁的争抢
    • 使用场景:并发竞争激烈
    • 优势:精准打击,不浪费时间片
    • 劣势:需要挂起协程,进行上下文切换,操作比较重
  • 自旋+CAS:基于自旋结合CAS的方式,反复校验锁的状态,并尝试获取锁
    • 使用场景:适用于并发竞争强度低的场景
    • 优势:无需协程阻塞,短期来看操作是比较轻的
    • 劣势:长时间竞争不到,浪费cpu时间片

sync.Mutex 结合了一下两种方案,制定了一个锁升级的过程,动态调整锁的态度(乐观——>悲观)

具体为

  • 首先保持乐观,使用自旋+CAS的策略争抢锁
  • 尝试持续受挫后(自旋累计四次),判断当前并发竞争激烈,由自旋转为 阻塞/挂起模式

饥饿模式(公平问题)

饥饿:非公平机制下,mutex阻塞队列中存在goroutine长时间取不到锁,从而陷入饥饿状态

饥饿模式:抢锁流程由非公平机制转为公平机制

转化场景

  1. 正常模式——>饥饿模式:当阻塞队列存在goroutine等锁超过1ms而不得,进入饥饿模式
  2. 饥饿模式——>正常模式:阻塞队列为空,或取得锁的goroutine等锁时间低于1ms

golang的mutex实现了 性能和公平之间的动态调整