python多线程、进程、协程以及并发、并行

1、多线程、多进程、协程

1.1 进程和线程

1.2 协程

(1)官方文档 asyncio — 异步 I/O
(2)其他参考
文章1:进程和线程、协程的区别
文章2:Python协程原理介绍及基本使用
文章3:Python的协程异步IO(asyncio)详解
B站【python】asyncio的理解与入门,搞不明白协程?

  • 这个视频里关于“await 协程对象”底层执行的逻辑讲解的有问题,作者在【python】await机制详解 这个视频最开始3min给出了纠正~~~

文章4:探索 Flask 对 asyncio 的支持
文章5:为什么用 async 异步的 FastAPI 阻塞了所有请求?

1.2.1 举例理解

1、类比:
(1) uvicorn类似tomcat容器:Uvicorn 默认情况下是单进程单线程的,但是它支持多协程,这是由于它基于异步 I/O 机制,可以并行处理多个请求 。

  • 当配置了 --workers 参数时,Uvicorn 可以启动多个工作进程,每个工作进程都是单线程的。
  • 底层是调用asyncio包的异步协程能力。
  • 如果希望 Uvicorn 在每个工作进程内部实现多线程处理,这不是 Uvicorn 的直接功能。但是,可以通过在应用层面使用线程或进程池来实现更细粒度的并行处理,或者使用其他支持多线程的 ASGI 服务器。

(2)fastapi类似spring框架:支持异步开发的python框架;

  • uvicorn.run(appname, host, ip,…)里appname:
    • 可以接受fastapi封装的app,也就是用户请求先被uvicorn转给fastapi下的app,再由app分发给对应的api接口。
    • 也可以接受str类型的app描述,具体:假设目录结构是A/src/a.py,在a.py中定义myapp=FastAPI(title=‘xxx’),在A/下执行python a.py来启动,那appname=‘src.a:myapp’。

(3)asyncio类似java里的异步开发三方包,底层是基于事件循环的单线程下的协程异步;

2、协程是基于事件循环的,是用户可控的。
举例:流水线(进程)上的员工A(员工是个线程),本来只干做饭的活(单任务,无需多任务协同),现在老板说,饭已经在电饭锅里煮着了(“饭做熟”这个过程需要等待),你现在反正也是闲着,去帮忙打扫下卫生(线程空闲时切换到其他任务协程切换),这样就从单任务变多任务协程。

  • 现在这个主线程去打扫卫生了,之前的煮饭被等待,那“饭做熟”虽然不需要主线程参与,但这个等待并不是停止,也就是说主线程把米放到了电饭锅,接着去干别的任务,“饭煮熟”这个任务其实是交给了电饭锅的煮饭功能了,而不是放锅里就一直是生米的状态。
  • 类比,那其实当单线程下做协程切换时,被等待的协程仍然需要被执行完成的。但是就1个主线程,主线程又去执行别的协同任务了,那这个“等待”里的任务(米在锅里从生到熟的变化)到底是谁在执行?
    • “等待”里的任务可以是操作系统内核 、用户自定义的子线程、额外的进程等不需要消耗主线程的方式来执行…
  • asyncio的实现原理是非阻塞IO
    (1)当应用程序发起一个非阻塞 I/O 请求时,操作系统内核会负责处理这个请求。如果数据还没有准备好(例如,网络数据包还未到达),内核会立即返回一个指示数据未准备好的信号给应用程序,而不会阻塞应用程序的线程。
    (2)对于许多类型的 I/O 设备,数据传输是由直接存储器访问(DMA)控制器来处理的。这意味着 I/O 设备可以直接向内存传输数据,而无需 CPU的介入。这样,即使 CPU 正在执行其他任务,数据传输也可以独立进行。
    总体,执行逻辑如下:
    ① 用户线程只用关注用户设定的任务,遇到需要等待的任务,可以切换到其他任务;
    ② 被等待的任务会由操作系统内核等不需要消耗主线程的方式来接手;
    ③ 当他把接手的任务执行完后,就会发出信号告诉主线程:“我已经把扔给我的等待任务做完了,你可以直接享用结果了!”
    ④ 用户线程收到这个信号,就去收割被等待任务的结果。
    ……那④中是“先停止当前正在执行的协程,然后立马去调度操作系统释放的信号结果”,还是“继续执行当前的协程,直到当前协程完成 或 被等待 或 达到某个检查点,才去重新调度操作系统释放的信号结果”呢?
    ……具体:asyncio 是通过事件循环来实现这个过程,事件循环event_loop会根据当前的任务状态和内部调度策略【具体是哪种??待学…】来决定何时执行被操作系统通知的任务。
1.2.2 协程和线程安全

参考:并发异步编程之争:协程(asyncio)到底需不需要加锁?(线程/协程安全/挂起/主动切换)Python3

其他:
协程虽然是单线程,但是仍支持把多个任务分发到线程池的不同子线程里,具体在线程或者进程池中执行代码 loop.run_in_executor()

2、python线程安全

python多线程下数据安全问题

3、python和java比较

(1)python 多线程是假的。

  • 因为GIL全局锁的存在,即使多线程下也只是让他们交替获得GIL锁,即每个线程都可以执行,但也只是“交替”执行,而不是真正的同时执行!同一时间下,即使是多CPU,也只有1个线程可以获得GIL锁,即也只能有一个线程可执行
  • python下多进程并行是真的。

(2)java下,多线程并发可以实现并行。

  • 如果是单个CPU,那效果和python多线程是一样的。
  • 如果是多个CPU,每个CPU上的线程互不影响,就会出现多线程下、同一时间点下、不同CPU上都有线程在跑,这样就真正实现了并发下的并行!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值