如何用 asyncio.Semaphore 限制并发任务数量
技术百科
舞姬之光
发布时间:2026-01-20
浏览: 次 asyncio.Semaphore通过acquire/release机制控制并发数,需在协程外统一创建并共享;推荐用async with自动管理;BoundedSemaphore可防止非法release导致计数错误。
用 asyncio.Semaphore 限制并发任务数量,核心是让每个协程在执行前先“申请许可”,拿到信号量才运行,完成后释放,从而控制同时运行的任务数。
创建并使用信号量控制并发数
初始化一个 Semaphore,传入最大允许的并发数量(比如 3),然后在协程中用 async with semaphore: 语句自动获取和释放。
- 信号量初始值即为最大并发数,每次
acquire()成功就减 1,release()加 1 -
async with semaphore:是推荐写法,确保异常时也能释放,避免死锁 - 所有需要限流的协程都必须共用同一个
Semaphore实例
典型用法示例
假设要并发请求 10 个 URL,但最多只允许 3 个 HTTP 请求同时发出:
import asyncio import aiohttpasync def fetch(session, url, semaphore): async with semaphore: # 这里会阻塞直到有空闲许可 async with session.get(url) as response: return await response.text()
async def main(): semaphore = asyncio.Semaphore(3) # 最多 3 个并发 urls = [f"https://www./link/5f69e19efaba426d62faeab93c308f5c"] * 10
async with aiohttp.ClientSession() as session: tasks = [fetch(session, url, semaphore) for url in urls] results = await asyncio.gather(*tasks) return results注意共享作用域和生命周期
信号量必须在所有目标协程可见的作用域内创建,且不能在循环内部重复新建:
- ❌ 错误:在 for 循环里每次 new 一个
Semaphore(3)→ 完全失去限流效果 - ✅ 正确:在
main()或更高层创建一次,作为参数传入或通过闭包共享 - 如果协程分布在不同模块或类中,可通过依赖注入、全局变量(不推荐)或上下文传递
与 asyncio.BoundedSemaphore 的区别
普通 Semaphore 允许 release() 次数超过初始值,而 BoundedSemaphore 会检查是否超出上限,防止误调用导致计数错乱:
- 日常限流用
Semaphore足够,只要确保每次
acquire()都配对async with或手动release() - 逻辑复杂、可能多次释放时,用
BoundedSemaphore更安全,它会在非法release()时抛出ValueError
# ai
# 会在
# 能在
# 也能
# 最多
# 可通过
# http
# 循环
# 并发
# 区别
# 并发请求
# 死锁
# 即为
# 作用域
# session
# 抛出
# 闭包
# for
# 全局变量
# 信号量
# 前先
相关栏目:
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
AI推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
SEO优化<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
技术百科<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
谷歌推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
百度推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
网络营销<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
案例网站<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
精选文章<?muma echo $count; ?>
】
相关推荐
- Python对象生命周期管理_创建销毁解析【教程】
- Windows如何使用BitLocker To G
- Windows11怎样开启游戏模式_Windows
- 如何在 Windows 11 中使用 AlomWa
- Win11怎么开启远程桌面_Win11系统远程桌面
- Win11怎么查看硬盘型号_Windows 11检
- Windows10蓝屏SYSTEM_SERVICE
- php8.4如何调用com组件_php8.4win
- Python随机数生成_random模块说明【指导
- 如何在同包不同文件中正确引用 Go 结构体
- 如何在Golang中捕获JSON序列化错误_Gol
- Win11怎么查看显卡温度 Win11任务管理器查
- Win11怎么设置桌面图标间距_Windows11
- 用Python构建微服务架构实践_FastAPI与
- Win11怎么忘记WiFi网络_Win11删除已保
- Win10如何更改任务栏高度_Windows10解
- Win11怎么卸载Photos应用_Win11卸载
- Win11怎么设置默认邮件客户端 Win11修改M
- Win11怎么关闭系统声音_Win11系统提示音静
- 静态属性修改会影响所有实例吗_php作用域操作符下
- Python配置文件操作教程_JSONINIYAM
- Win11怎么开启远程桌面连接_Windows11
- php485在php5.6下能用吗_php485旧
- Win10怎么卸载剪映_Win10彻底卸载剪映方法
- Win10怎么设置开机密码_Windows10账户
- php怎么下载安装并配置环境变量_命令行调用PHP
- 如何在Golang中处理数据库事务错误_回滚和日志
- Python技术债务管理_长期维护解析【教程】
- Win11怎么关闭VBS安全性_Windows11
- Win11怎么关闭开机声音_Win11系统启动提示
- Windows怎样拦截QQ浏览器广告_Window
- Go 中实现 Python urllib.quot
- mac怎么退出id_MAC退出iCloud账号与A
- Win11怎么关闭任务栏小组件_Windows11
- Win11如何设置电源计划_Win11电源计划优化
- 如何使用Golang写入二进制文件_Golang
- Laravel 查询 JSON 列:高效筛选包含数
- 如何使用Golang实现容器健康检查_监控和自动重
- Win10任务栏天气和资讯怎么关闭 Win10禁用
- VSC怎样在Linux运行PHP_Ubuntu系统
- Win11怎么退出高对比度模式_Win11取消反色
- Win11怎么设置触控板手势_Windows11三
- Win11怎么禁用键盘自带键盘_Win11笔记本禁
- c++如何使用std::bind绑定函数参数_c+
- Win11怎么设置系统还原_Windows11系统
- Win10怎么卸载迅雷_Win10彻底卸载迅雷方法
- 如何在Golang中实现服务熔断与限流_Golan
- 如何在 VS Code 中正确配置并使用 NumP
- MAC的“接续互通”功能无法使用怎么办_MAC检查
- Win10怎样清理C盘爱奇艺缓存_Win10清理爱


QQ客服