Классическая идея (ещё из C) - делать это с помощью каналов, вот как это должно быть устроено:
вы заводите канал, который будет играть роль семафора (мьютекса со счетчиком), пишете туда столько байт, сколько хотите максимум запускать сопрограмм, перед запуском каждой из них вычитываете один байт из канала, при завершении пишете его туда же. Таким нехитрым образом вы получаете ограничение сверху на число одновременно запущенных сопрограмм.
Вот пример кода:
Из вот этой книжки, рекомендую прочитать, кстати: