Семафор из канала
Экспорт архивов снова вис на диске, как в. Миша вернулся к старому семафору экспорта — буферизованному каналу, где отправка занимала место, а приём возвращал его.
буферизованный канал на 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
Проверьте себя
Что такое acquire/release в семафоре из канала?
Семафор ограничивает что?
Чем семафор удобнее пула на лету?
правильных ответов
Канал на N — N разрешений; acquire — отправка, release — приём через defer. Простейший и самый частый лимитер параллелизма в Go.
10 000 ₽ · 60 минут · онлайн