Ответ
sync.Mutex
в Go имеет два режима работы, которые он переключает автоматически для оптимизации производительности и справедливости:
Нормальный режим (Normal mode)
- Когда используется: Когда мьютекс свободен или конкуренция за него невысока.
- Как работает: Горутины, запрашивающие мьютекс, сначала пытаются захватить его с помощью атомарных операций (spin-loop) в течение короткого времени. Это очень быстро, если мьютекс освобождается почти сразу, и позволяет избежать затрат на переключение контекста горутины. Если захватить мьютекс не удалось, горутина уходит в ожидание.
- Недостаток: В этом режиме возможна ситуация "захвата на опережение" (barging), когда новая горутина может перехватить мьютекс у горутины, которая уже давно стоит в очереди.
Режим голодания (Starvation mode)
- Когда используется: Мьютекс переходит в этот режим, если горутина ожидает освобождения дольше 1 миллисекунды.
- Как работает: В этом режиме мьютекс передается строго по очереди — от освободившей его горутины к той, что дольше всех ждет в очереди. Новые горутины не могут его захватить, даже если он свободен, а становятся в конец очереди.
- Цель: Обеспечить справедливость и предотвратить ситуацию, когда некоторые горутины никогда не получают доступ к ресурсу.
package main
import "sync"
var mu sync.Mutex
func criticalSection() {
mu.Lock() // Захват мьютекса. Горутина может войти в ожидание.
// ... критическая секция ...
mu.Unlock() // Освобождение мьютекса для других горутин.
}
Эта двухрежимная система позволяет sync.Mutex
быть одновременно высокопроизводительным при низкой конкуренции и справедливым при высокой.