Тонкости weighted †
На ревью генерации превью Аня показала две тонкости: TryAcquire не обгонял ждущих и сразу возвращал false, а Release паниковал при переборе бюджета. Миша записал обе в договор стадии.
у взвешенного семафора два неочевидных поведения: TryAcquire не проскакивает очередь ждущих — при их наличии сразу возвращает false, а Release паникует, если вернуть больше бюджета, чем было занято.
TryAcquire и очередь
if sem.TryAcquire(10) {
defer sem.Release(10)
makePreview()
} else {
fallback()
}
TryAcquire — неблокирующая попытка: метод никогда не ждёт и в очередь не встаёт. Неочевидное: если в очереди уже стоят горутины, ждущие Acquire, TryAcquire не проскакивает мимо них — он немедленно возвращает false, даже если бюджета для запроса хватает. Казалось бы, «попробовать» должно быть дешевле, но попытка не имеет права опередить ждущих — иначе «пробующие» голодали бы «ждущих». Получил false — делай fallback.
Release паникует при переборе
sem.Release(10) // panic: semaphore: released more than held
Release требует ровно то, что было занято. Вернуть больше бюджета — паника, и это хорошо: перебор бюджета — симптом рассогласования Acquire/Release, который иначе тихо разъел бы лимит. Симметрию держит тот же приём, что и раньше: defer sem.Release(вес) сразу после успешного Acquire.
Что это значит на практике
Обе тонкости — про дисциплину. Мгновенный false у TryAcquire означает: «попробовал — не прошло, делай fallback», но обойти очередь ждущих нельзя. Паника Release означает: несовпадение весов — баг, который должен падать сразу, а не копиться. В продакшене это пара «Acquire(ctx, n) + defer Release(n)» и ничего больше.
Вы узнаете:
- почему паника при переборе лучше молчаливого варианта
- как TryAcquire реализует backpressure
Проверьте себя
sem.Release(1) при пустом бюджете (ничего не занято). Что произойдёт?
В очереди стоит горутина, но свободный бюджет есть. Что вернёт TryAcquire?
Вес задачи в Acquire и Release вычисляется заново дважды. Чем грозит?
правильных ответов
TryAcquire неблокирующий: false при нехватке бюджета или при наличии ждущих; Release паникует при переборе. Обе тонкости держат лимит честным, а баги — громкими.
10 000 ₽ · 60 минут · онлайн