协程,线程和进程的区别
-
多线程:多进程通常利用的是多核 CPU 的优势,同时执行多个计算任务。每个进程有自己独立的内存管理,所以不同进程之间要进行数据通信比较麻烦。
-
多线程:多线程是在一个 cpu 上创建多个子任务,当某一个子任务休息的时候其他任务接着执行。多线程的控制是由 python 自己控制的。 子线程之间的内存是共享的,并不需要额外的数据通信机制。但是线程存在数据同步问题,所以要有锁机制。
-
多协程:协程的实现是在一个线程内实现的,相当于流水线作业。协程是一个线程中执行,没有线程切换的开销,所以对于并发编程,可以优先使用协程。
asyncio
在Python的asyncio库中,async
和await
是用于异步编程的关键字,引入了异步/协程(coroutine)的概念
异步编程是一种处理并发任务的方式,使得程序能够在等待某些I/O操作(如文件读写、网络请求等)的同时继续执行其他任务,而不会发生阻塞。作用:
-
提高程序效率:异步编程可以充分利用I/O等待时间,使得程序在等待操作完成时能够继续执行其他任务,从而提高了整体程序的效率。
-
改善用户体验:在网络编程中,异步操作可以避免阻塞用户界面,使得应用程序更加流畅。
-
简化并发编程:通过使用async和await关键字,可以更方便地编写并发程序,避免了传统多线程编程中的锁和同步问题。
用法:
-
定义异步函数,使用async关键字
-
在异步函数中,使用await 关键字执行可等待对象(Coroutine、Task、Future),等待子函数执行完成,再往下执行。(在并发操作中,把程序控制权教给主程序,让他分配其他协程执行。) await 只能在带有 async 关键字的函数中运行。
-
通过
asyncio.create_task()
/asyncio.gather()
创建任务 -
asyncio.run
运行任务
# 定义异步函数
async def fetch_data(index):
print(f"Fetching data {index}...")
await asyncio.sleep(2) # 模拟网络请求
print(f"Data {index} fetched.")
return f"Data {index}"
async def main():
tasks = [fetch_data(i) for i in range(2)]
results = await asyncio.gather(*tasks)
print("All data fetched:", results)
# 执行任务
asyncio.run(main())
asyncio.create_task()
用于创建一个协程任务,接受一个协程对象作为参数,并返回一个任务对象,该任务对象可以用来控制和管理该协程的执行,包括取消、等待其执行完成等
asyncio.gather()
用于同时运行多个协程,并等待全部完成。接受一系列的协程对象(或者 Future 对象)作为参数,并返回一个协程对象,该协程对象会在所有给定的协程都执行完毕后完成
asyncio.run
函数运行协程程序,协程函数作为参数传入
在一个async
函数内部,通过await
可以调用另一个async
函数,这个调用看起来是串行执行的,但实际上是由asyncio
内部的消息循环控制;
在一个async
函数内部,通过await asyncio.gather()
可以并发执行若干个async
函数。