← 中文资源

简体中文版本

用 tokio 信号量限制异步并发

在多个 spawned 任务间共享 Arc<Semaphore>,每个任务持有许可直至完成,用 JoinSet 等待并汇总全部结果。

阅读英文原文

功能说明

示例用 Arc<Semaphore> 在多个 spawned 任务之间共享并发上限。每个任务先调用 acquire_owned() 拿到许可,许可在任务结束前一直持有,因此同一时刻最多只有 Semaphore::new(2) 个任务进入临界区。所有任务交给 JoinSet 管理,主任务通过 join_next 收集结果并排序输出。

关键代码

let _permit = permits.acquire_owned().await.expect("semaphore closed");
sleep(Duration::from_millis(30)).await;
id * id

绑定到 _permit 而不是 _,许可才会活到任务结束;_ 会立即丢弃,限流失效。

使用注意

  • acquire_owned 需要 Arc<Semaphore>,返回的许可拥有所有权,适合在 'static 任务中持有。
  • 任务 panic 时许可随栈展开释放,不会永久占用。
  • JoinSet 只保证收集结果,不保证完成顺序;示例最后排序以获得稳定输出。
  • 许可数量应按下游承载能力设置,过小会排队,过大会压垮依赖。
  • 如果需要等待超时,可在 acquire_owned 外层再包 tokio::time::timeout。

验证方式

示例启动 6 个任务、上限 2、每个任务 30 毫秒,总耗时约 90 毫秒,输出排序后为 [0, 1, 4, 9, 16, 25]。把上限改为 1 可观察耗时变为约 180 毫秒。