在 Go 语言中,互斥锁 Mutex 存在哪几种内部状态?请分述每种状态的含义及其在锁竞争过程中的作用。
考察说明
考察对 Go 语言 Mutex 内部状态机的理解,包括正常模式和饥饿模式以及它们之间的切换机制。
回答思路
- 【回答框架 1】Go 的 Mutex 是混合互斥锁,其内部状态主要包括 mutexLocked(锁定)、mutexWoken(唤醒)、mutexStarving(饥饿)以及 mutexWaiterShift(等待者计数偏移),这些状态组合用于表示锁的当前情况。
- 【回答框架 2】正常运行模式下,新到达的 goroutine 有机会优先抢占锁,即使有等待者;这种模式可以减少上下文切换,提高吞吐量,但可能导致等待时间过长,产生饥饿。
- 【回答框架 3】当锁处于饥饿模式时,锁会优先分配给等待队列中的第一个 goroutine,新到达的 goroutine 必须排队等待,防止等待超过 1ms,确保公平性。
- 【回答框架 4】状态切换条件:当等待者等待时间超过 1ms 时,锁进入饥饿模式;当持有锁的 goroutine 释放锁且发现没有等待者或等待时间小于 1ms 时,锁退出饥饿模式。
- 【关键点 1】Mutex 状态由互斥锁的状态字段表示,包含 locked、woken、starving 和 waiter 计数。
- 【关键点 2】正常模式有利于性能,饥饿模式保证公平性,两者根据等待时间动态切换。
- 【关键点 3】饥饿模式阈值是 1ms,超过则可能进入饥饿模式。
- 【易错点 1】误以为 Mutex 只有锁定和未锁定两种状态,忽略饥饿模式和唤醒状态。
- 【易错点 2】将饥饿模式理解为总是让所有等待者按 FIFO 获取锁,实际仅在饥饿模式且等待者等待超时后才严格 FIFO。
- 【易错点 3】忽略 Mutex 状态切换对性能的影响,过度依赖饥饿模式可能导致吞吐量下降。