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

Weighted: веса и бюджет

Генерация превью: лёгкие страницы почти ничего не стоили, а тяжёлые отчёты съедали сотни мегабайт памяти. Лимит «пять одновременных» душил лёгкие задачи и пропускал пять тяжёлых. Миша перешёл от штук к бюджету: каждая задача объявила свой вес.

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

взвешенный семафор меряет не число операций, а объём ресурса: каждая операция занимает свой вес, и лимит — это бюджет, а не счётчик штук.

Почему штуки не подходят

Обычный семафор считает операции штуками: каждая занимает ровно одно разрешение. Но ресурс, который мы ограничиваем, часто расходуется неравномерно. Одна задача держит соединение, другая — пятьдесят мегабайт памяти, третья — оба сразу. При лимите «5 одновременных операций» пять задач по пятьдесят мегабайт пролезут без проблем, а пять лёгких упрутся в тот же потолок, хотя могли бы работать параллельно. Нужен семафор, который меряет объём ресурса.

Бюджет в единицах ресурса

sem := semaphore.NewWeighted(100) // бюджет: 100 единиц ресурса

if err := sem.Acquire(ctx, 50); err != nil {
    return err            // отменены: вес не занят
}
defer sem.Release(50)     // возвращаем ровно занятое

if err := sem.Acquire(ctx, 1); err != nil { // лёгкая задача на 1 единицу
    return err
}
defer sem.Release(1)

Тяжёлая задача занимает половину бюджета, лёгкая — сотую. Одновременно может работать: две тяжёлые, или одна тяжёлая и пятьдесят лёгких, или сто лёгких. Лимит выражает реальный ресурс — мегабайты, соединения, токены, — а не «число горутин». Ошибку Acquire проверяют до defer Release: при отменённом контексте вес не занят, и возврат незанятого веса тихо раздул бы бюджет.

Acquire(ctx, n)

Acquire(ctx, n) ведёт себя как одиночное разрешение из прошлого урока, только с учётом веса: ждёт, пока освободится n единиц бюджета, отменяется по контексту, ничего не теряя. Release(n) возвращает ровно n — несовпадение весов с Acquire — это ошибка в коде, и про парность заботится тот же defer.

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

Вы узнаете:

  • как выбирать единицу бюджета
  • как взвешенный лимит работает для пула соединений разного калибра
Задание · вопросы

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

Вопрос 1 из 3

Как выбрать единицу бюджета взвешенного семафора?

Вопрос 2 из 3

Что делает Weighted, если все веса равны 1?

Вопрос 3 из 3

Release больше занятого — что произойдёт?

Итоги

Weighted: лимит — бюджет в единицах ресурса; каждая операция объявляет свой вес; Acquire(ctx, n)/Release(n) симметричны и держатся на defer после проверки ошибки. Это concurrency limit, выраженный в ресурсе, а не в штуках.

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