Mutex有两种操作模式:正常模式和饥饿模式。在正常模式下,等待者以FIFO顺序排队,但是唤醒的等待者并不拥有锁,它与新到达的goroutine竞争所有权。新到达的goroutine具有优势——它们已经在CPU上运行,而且可能有很多个,因此被唤醒的等待者有很大的机会输掉竞争。在这种情况下,它将排在等待队列的前面。如果一个等待者无法在1毫秒内获取锁,则将mutex切换到饥饿模式。
在饥饿模式下,mutex的所有权直接从解锁goroutine转移给队列前面的等待者。即使看起来未被锁定,新到达的goroutine也不会尝试获取mutex,也不会尝试自旋。相反,它们将自己排队到等待队列的尾部。
如果等待者接收到mutex的所有权并发现(1)它是队列中的最后一个等待者,或者(2)它等待的时间少于1毫秒,则将mutex切换回正常操作模式。
正常模式的性能要比饥饿模式好得多,因为goroutine可以连续多次获取mutex,即使有阻塞的等待者。饥饿模式非常重要,以防止尾延迟的病态情况。