网络语言系列&go系列【仅供参考】:Golang互斥锁正常模式和饥饿模式的区别




Golang互斥锁正常模式和饥饿模式的区别

Golang互斥锁(sync.Mutex)的正常模式和饥饿模式是两种不同的锁获取策略,旨在平衡性能和公平性。以下是两者的详细区别:

正常模式(非公平锁)

1. 锁获取方式:

  1. 当一个goroutine持有锁时,其他goroutine会尝试通过自旋或阻塞等待锁释放。

  2. 自旋是指goroutine在等待锁释放时不会立即阻塞,而是会循环检查锁的状态,以期望在锁被释放时立即获取到锁。

  3. 如果自旋次数超过一定限制(如4次)或满足其他条件(如等待时间超过1毫秒、CPU核数大于1等),goroutine会进入阻塞状态,等待锁的持有者释放锁后唤醒。

2. 等待队列:

  1. 所有等待锁的goroutine会按照先进先出(FIFO)的顺序排队等待。

  2. 被唤醒的goroutine不会直接拥有锁,而是会和新请求锁的goroutine竞争锁。

  3. 新请求锁的goroutine在CPU上执行,且可能有多个,因此刚刚唤醒的goroutine在锁竞争中可能失败。

3. 性能特点:

  1. 正常模式下,锁的获取相对高效,因为goroutine可以通过自旋来减少阻塞和上下文切换的开销。

  2. 但长时间等待锁的goroutine可能会因为无法获取到锁而切换到饥饿模式。

饥饿模式(公平锁)

1. 锁获取方式:

  1. 当一个goroutine等待锁的时间超过一定阈值(如1毫秒)时,互斥锁会切换到饥饿模式。

  2. 在饥饿模式下,新请求锁的goroutine不会参与抢锁,也不会进入自旋状态,而是直接进入等待队列的尾部。

  3. 锁的所有权会直接交给等待队列中排在第一位的goroutine。

2. 等待队列:

饥饿模式下,等待队列中的goroutine会按照顺序依次获取锁,避免了长时间等待锁的goroutine无法获取到锁的问题。

3. 性能特点:

  1. 饥饿模式下,锁的获取更加公平,但性能会下降。

  2. 因为新请求锁的goroutine需要等待队列中的其他goroutine获取到锁后才能获取锁,这增加了等待时间和上下文切换的开销。

  3. 但饥饿模式可以避免因长时间等待锁而导致的高尾延时问题。

切换条件

  • 互斥锁会在以下情况下从正常模式切换到饥饿模式:

    • 一个goroutine等待锁的时间超过1毫秒。

    • 等待队列不为空,且新请求锁的goroutine在队列末尾或等待时间较短时,锁会尝试切换回正常模式。

使用建议

  • 在编写业务逻辑时,应尽量避免全局使用同一个Mutex,以减少锁竞争和等待时间。

  • 加锁后立即使用defer语句对其解锁,以避免死锁问题。

  • 根据具体业务场景选择合适的锁模式。如果业务场景对性能要求较高且可以容忍一定的不公平性,可以选择正常模式;如果对公平性要求较高且可以容忍一定的性能下降,可以选择饥饿模式。

综上所述,Golang互斥锁的正常模式和饥饿模式在锁获取策略、等待队列、性能特点等方面存在显著差异。开发者应根据具体业务场景和需求选择合适的锁模式以实现最佳性能和公平性。







ac-er8888

Golang互斥锁正常模式和饥饿模式的区别

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

坦笑&&life

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值