0

0

Python并发系统学习路线第215讲_核心原理与实战案例详解【技巧】

冰川箭仙

冰川箭仙

发布时间:2025-12-27 23:23:02

|

534人浏览过

|

来源于php中文网

原创

Python并发稳定需避免隐式阻塞、上下文切换失控、资源竞争未加锁及协程混入同步I/O;asyncio.run()不可嵌套调用,因内部检查并拒绝已在运行的事件循环;应顶层调用,内部用await或create_task();跨同步异步边界宜用to_thread()(Py3.9+)或run_in_executor();协程间共享状态必须用asyncio.Lock且按资源独立实例化。

python并发系统学习路线第215讲_核心原理与实战案例详解【技巧】

Python 并发不是靠多开几个 threading.Thread 或塞一堆 asyncio.create_task() 就能稳的——真正卡住系统的,往往是隐式阻塞、上下文切换失控、资源竞争没加锁,或者协程里混进了同步 I/O。

为什么 asyncio.run() 不能嵌套调用

这是初学者最常撞上的硬错误。当你在已运行的事件循环里再调用 asyncio.run(),会直接抛出 RuntimeError: asyncio.run() cannot be called from a running event loop

  • 根本原因:asyncio.run() 内部会检查当前线程是否已有运行中的事件循环,有就拒绝启动
  • 常见场景:在 Flask/FastAPI 的请求处理函数中、或某个已由 asyncio.run() 启动的协程里,又写了 asyncio.run(some_coro())
  • 正确做法:顶层用 asyncio.run() 启动;内部一律用 awaitasyncio.create_task();若需从同步代码“切”进异步上下文(如线程中),改用 asyncio.get_event_loop().create_task()(注意循环存在性)或 asyncio.to_thread()(Py3.9+)

concurrent.futures.ThreadPoolExecutorasyncio.to_thread() 怎么选

两者都用于把阻塞操作“搬出”主线程,但适用阶段和控制粒度不同。

  • ThreadPoolExecutor 是传统线程池,适合长期复用、需精细控制线程数(如 max_workers=4)、或要统一管理生命周期(.shutdown(wait=True))的场景
  • asyncio.to_thread()(Py3.9+)更轻量,每次调用自动分配线程并 await 返回,适合零散、偶发的阻塞调用(如读文件、调用旧版同步 SDK)
  • 关键区别:前者不返回协程对象,需配合 loop.run_in_executor() 才能 await;后者直接返回可 await 的协程
import asyncio
import time

错误:直接 await 同步函数 → 主线程卡死

await time.sleep(1)

正确(Py3.9+)

await asyncio.to_thread(time.sleep, 1)

Amazon Nova
Amazon Nova

亚马逊云科技(AWS)推出的一系列生成式AI基础模型

下载

立即学习Python免费学习笔记(深入)”;

或兼容老版本

loop = asyncio.get_running_loop() await loop.run_in_executor(None, time.sleep, 1)

asyncio.Lock 保护共享状态,但别锁错对象

协程并发下,threading.Lock 完全无效——它只对线程起作用,而多个协程可能跑在同一个线程里。

  • 必须用 asyncio.Lock,且每个需要保护的共享变量/资源应配独立的锁实例
  • 典型错误:所有协程共用一个全局 lock = asyncio.Lock(),结果本该互斥的两个不同资源(比如用户余额和订单号生成器)被强绑定,造成不必要等待
  • 更隐蔽的问题:在类方法中定义 self.lock = asyncio.Lock(),但忘记 await self.lock.acquire(),或忘了 try/finally 释放
class Counter:
    def __init__(self):
        self.value = 0
        self.lock = asyncio.Lock()  # 每个实例独享锁
async def increment(self):
    async with self.lock:  # 自动 acquire/release
        self.value += 1
        return self.value

并发真正的复杂点不在语法,而在你是否清楚每一行代码执行时,CPU 在哪、IO 在哪、锁在哪、事件循环有没有被意外阻塞——这些不会报错,但会让吞吐量掉一半、延迟毛刺翻倍、压测时连接池耗尽。留心那些没显式写 await 却实际会阻塞的调用,比如某些数据库驱动的 .execute()、日志库的同步刷盘、甚至 json.loads() 处理超大字符串。

相关专题

更多
python开发工具
python开发工具

php中文网为大家提供各种python开发工具,好的开发工具,可帮助开发者攻克编程学习中的基础障碍,理解每一行源代码在程序执行时在计算机中的过程。php中文网还为大家带来python相关课程以及相关文章等内容,供大家免费下载使用。

709

2023.06.15

python打包成可执行文件
python打包成可执行文件

本专题为大家带来python打包成可执行文件相关的文章,大家可以免费的下载体验。

625

2023.07.20

python能做什么
python能做什么

python能做的有:可用于开发基于控制台的应用程序、多媒体部分开发、用于开发基于Web的应用程序、使用python处理数据、系统编程等等。本专题为大家提供python相关的各种文章、以及下载和课程。

737

2023.07.25

format在python中的用法
format在python中的用法

Python中的format是一种字符串格式化方法,用于将变量或值插入到字符串中的占位符位置。通过format方法,我们可以动态地构建字符串,使其包含不同值。php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

616

2023.07.31

python教程
python教程

Python已成为一门网红语言,即使是在非编程开发者当中,也掀起了一股学习的热潮。本专题为大家带来python教程的相关文章,大家可以免费体验学习。

1235

2023.08.03

python环境变量的配置
python环境变量的配置

Python是一种流行的编程语言,被广泛用于软件开发、数据分析和科学计算等领域。在安装Python之后,我们需要配置环境变量,以便在任何位置都能够访问Python的可执行文件。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

547

2023.08.04

python eval
python eval

eval函数是Python中一个非常强大的函数,它可以将字符串作为Python代码进行执行,实现动态编程的效果。然而,由于其潜在的安全风险和性能问题,需要谨慎使用。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

573

2023.08.04

scratch和python区别
scratch和python区别

scratch和python的区别:1、scratch是一种专为初学者设计的图形化编程语言,python是一种文本编程语言;2、scratch使用的是基于积木的编程语法,python采用更加传统的文本编程语法等等。本专题为大家提供scratch和python相关的文章、下载、课程内容,供大家免费下载体验。

695

2023.08.11

ip地址修改教程大全
ip地址修改教程大全

本专题整合了ip地址修改教程大全,阅读下面的文章自行寻找合适的解决教程。

27

2025.12.26

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
最新Python教程 从入门到精通
最新Python教程 从入门到精通

共4课时 | 0.6万人学习

Django 教程
Django 教程

共28课时 | 2.5万人学习

SciPy 教程
SciPy 教程

共10课时 | 0.9万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号