08-27-周三_17-09-29
This commit is contained in:
161
Python/Python并发编程/协程.md
Normal file
161
Python/Python并发编程/协程.md
Normal file
@@ -0,0 +1,161 @@
|
||||
# 协程
|
||||
|
||||
协程(Coroutine)是用户态的轻量级线程,由程序自身控制调度,通过协作式多任务实现并发。它能在单线程内挂起和恢复执行,无需操作系统介入,切换开销极小,尤其适合 I/O 密集型任务(如网络请求、文件读写)。
|
||||
|
||||
**与线程/进程对比**:
|
||||
|
||||
- **资源消耗**:协程内存占用更低(共享进程内存),线程需独立栈空间,进程资源消耗最大
|
||||
- **切换开销**:协程切换在用户态完成,速度极快;线程/进程切换依赖操作系统,开销较大
|
||||
- **适用场景**:协程适合高并发 I/O 操作;线程适合 CPU 密集型任务;进程适合多核并行计算
|
||||
|
||||
**核心优势**:
|
||||
|
||||
- **高并发**:单线程可处理数千级并发连接(如 Web 服务器)
|
||||
- **无锁机制**:避免多线程同步问题(如死锁、竞态条件)
|
||||
- **代码简洁**:用同步语法写异步逻辑,避免回调地狱
|
||||
|
||||
# 实现方式
|
||||
|
||||
## 生成器函数
|
||||
|
||||
通过 yield 暂停执行并传递值:需要手动管理状态,适用简单场景
|
||||
|
||||
```python
|
||||
def simple_coroutine():
|
||||
print("协程启动")
|
||||
x = yield # 暂停点,等待外部传入值
|
||||
print(f"接收值: {x}")
|
||||
|
||||
coro = simple_coroutine()
|
||||
next(coro) # 启动协程,执行到第一个 yield
|
||||
coro.send(10) # 恢复执行,x 赋值为 10
|
||||
|
||||
```
|
||||
|
||||
## async/await
|
||||
|
||||
通过 asyncio 库实现异步编程
|
||||
|
||||
```python
|
||||
import asyncio
|
||||
|
||||
|
||||
async def fetch_data(url):
|
||||
print(f"请求 {url}")
|
||||
await asyncio.sleep(1) # 挂起协程,让出控制权给事件循环,模拟异步等待
|
||||
return f"来自 {url} 的数据"
|
||||
|
||||
|
||||
async def main():
|
||||
tasks = [fetch_data("url1"), fetch_data("url2")]
|
||||
results = await asyncio.gather(*tasks) # 实现多任务并发调度:并发执行
|
||||
print(results)
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
|
||||
```
|
||||
|
||||
# 基本语法
|
||||
|
||||
**定义协程函数**
|
||||
|
||||
使用 `async def` 声明协程函数
|
||||
|
||||
```python
|
||||
import asyncio
|
||||
|
||||
async def my_coroutine():
|
||||
print("协程开始")
|
||||
await asyncio.sleep(1) # 模拟 I/O 操作
|
||||
print("协程结束")
|
||||
|
||||
```
|
||||
|
||||
**运行协程**
|
||||
|
||||
协程需要通过**事件循环**执行
|
||||
|
||||
```python
|
||||
async def main():
|
||||
await my_coroutine() # 等待协程完成
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
```
|
||||
|
||||
# 事件循环
|
||||
|
||||
事件循环是协程的调度核心,负责执行、切换和监控协程任务
|
||||
|
||||
```python
|
||||
import asyncio
|
||||
|
||||
|
||||
async def task1():
|
||||
print("任务1开始")
|
||||
await asyncio.sleep(2)
|
||||
print("任务1结束")
|
||||
|
||||
|
||||
async def task2():
|
||||
print("任务2开始")
|
||||
await asyncio.sleep(1)
|
||||
print("任务2结束")
|
||||
|
||||
|
||||
async def main():
|
||||
await asyncio.gather(task1(), task2()) # 并发执行多个协程
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
|
||||
```
|
||||
|
||||
# 进阶用法
|
||||
|
||||
## 任务
|
||||
|
||||
将协程封装为任务,更灵活地控制执行
|
||||
|
||||
```python
|
||||
async def main():
|
||||
task = asyncio.create_task(my_coroutine()) # 创建任务
|
||||
await task # 等待任务完成
|
||||
```
|
||||
|
||||
## 超时控制
|
||||
|
||||
设置协程执行的超时时间
|
||||
|
||||
```python
|
||||
async def slow_task():
|
||||
await asyncio.sleep(10)
|
||||
|
||||
async def main():
|
||||
try:
|
||||
await asyncio.wait_for(slow_task(), timeout=3)
|
||||
except asyncio.TimeoutError:
|
||||
print("任务超时")
|
||||
|
||||
```
|
||||
|
||||
## 协程同步
|
||||
|
||||
使用锁 `Lock` 保护共享资源
|
||||
|
||||
```python
|
||||
lock = asyncio.Lock()
|
||||
|
||||
async def safe_write():
|
||||
async with lock: # 异步上下文管理器
|
||||
# 安全地操作共享资源
|
||||
pass
|
||||
```
|
||||
|
||||
# 课后作业
|
||||
|
||||
- [必须] 动手完成本章节案例
|
||||
- [扩展] 阅读官方文档相关章节
|
||||
- [扩展] 用协程实现进程章节的爬虫案例
|
Reference in New Issue
Block a user