Материал проходит вычитку — возможны неточности.
Урок 13 из 118

x/sync/semaphore и отмена

Rate limiter победил 429, но отменённые клиентом запросы висели в очереди на слот. Миша взял семафор из x/sync: Acquire принимал контекст и выходил по отмене, не занимая разрешение.

Главная мысль

golang.org/x/sync/semaphore — семафор с отменой: Acquire(ctx, n) ждёт разрешения и умеет отменяться по контексту, не теряя разрешение.

Acquire с контекстом

sem := semaphore.NewWeighted(8)

if err := sem.Acquire(ctx, 1); err != nil {
    return err // отменены, пока ждали
}
defer sem.Release(1)

recognize(ctx, f)

Канал-семафор из умел только блокироваться. У пакетного семафора Acquire принимает контекст: если ctx отменён, пока горутина ждёт разрешения, Acquire возвращает ошибку и не занимает разрешение. Это главное отличие: с каналом горутина могла бы занять токен в момент отмены и утечь вместе с ним.

Где это важно

Сценарий: горутина ждёт свободный слот на вызов внешнего API распознавания, а запрос тем временем отменяют (клиент закрыл вкладку). С каналом-семафором она так и будет висеть в очереди (или займёт токен и зависнет дальше). С Acquire(ctx, 1) — выйдет сразу с ошибкой context.Canceled. Для сервисов, где отмена — норма жизни, это не мелочь, а защита от копящихся «ждунов».

Пара Acquire/Release

if err := sem.Acquire(ctx, 1); err != nil {
    return err
}
defer sem.Release(1)

Симметрия: успешный Acquire — и тут же defer Release. Возврат случится при любом выходе из функции, и про парность можно не думать. Успех Acquire — единственная точка, где разрешение занято, поэтому утечка разрешений возможна только при явной ошибке в коде.

В следующем уроке

Вы узнаете:

  • чем пакетный семафор тяжелее канала
  • как Acquire ведёт себя при уже отменённом ctx
Задание · вопросы

Проверьте себя

Вопрос 1 из 3

Что делает Acquire(ctx, n) при отмене контекста во время ожидания?

Вопрос 2 из 3

Канал-семафор при отмене ctx во время ожидания слота. Что происходит?

Вопрос 3 из 3

Release без успешного Acquire. Что это?

Итоги

x/sync/semaphore: Acquire с контекстом — отмена без потери разрешения; пара Acquire/defer Release. Дальше — веса, ради которых пакет и назван Weighted.

Наш сайт собирает куки. Чтобы тебе было удобнее им пользоваться. Нажимая на кнопку, ты даёшь разрешение собирать куки