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

Семафор из канала

Экспорт архивов снова вис на диске, как в. Миша вернулся к старому семафору экспорта — буферизованному каналу, где отправка занимала место, а приём возвращал его.

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

буферизованный канал на N мест — это семафор на N разрешений: горутина занимает место перед работой и возвращает его после, а defer гарантирует возврат.

Acquire/release на канале

sem := make(chan struct{}, 3) // 3 разрешения

sem <- struct{}{} // acquire: занять место
defer func() { <-sem }() // release: вернуть место

doWork()

Канал на 3 — три «токена». Отправка занимает токен; когда буфер полон, отправка блокируется — горутина ждёт разрешения. Приём возвращает токен. Defer гарантирует возврат на любом пути — включая панику.

Ограничить параллелизм

for _, item := range items {
    sem <- struct{}{}
    go func(item int) {
        defer func() { <-sem }()
        process(item)
    }(item)
}

Здесь семафор ограничивает, сколько горутин одновременно исполняют process — не больше 3. Плюс семафора перед воркер-пулом: горутин можно заводить по одной на задачу, а семафор сам «притормозит» лишние — они просто заблокируются на acquire.

Семафор как инструмент

Вспомни: тот же приём ограничивал число одновременных блокирующих syscall'ов. Канал-семафор — универсальный лимитер: база, диск, внешний API. Дефицитный ресурс → семафор на его ёмкость.

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

Вы узнаете:

  • когда горутина-на-задачу с семафором удобнее пула
  • как таймаут на acquire работает через select
Задание · вопросы

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

Вопрос 1 из 3

Что такое acquire/release в семафоре из канала?

Вопрос 2 из 3

Семафор ограничивает что?

Вопрос 3 из 3

Чем семафор удобнее пула на лету?

Итоги

Канал на N — N разрешений; acquire — отправка, release — приём через defer. Простейший и самый частый лимитер параллелизма в Go.

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