协程适用于IO阻塞且需要大量并发的场景,当发生IO阻塞,由协程的调度器进行调度,通过将数据流yield掉,并且记录当前栈上的数据,阻塞完后立刻再通过线程恢复栈,并把阻塞的结果放到这个线程上去运行 。

文章插图
下面,将针对在不同的应用场景中如何选择使用Python中的进程,线程,协程进行分析 。

文章插图
如何选择?在针对不同的场景对比三者的区别之前,首先需要介绍一下python的多线程(一直被程序员所诟病,认为是"假的"多线程) 。
那为什么认为Python中的多线程是“伪”多线程呢?更换上面multiprocessing示例中,p=multiprocessing.Process(target=count,args=(i,))为 p=threading.Thread(target=count,args=(i,)),其他照旧,运行结果如下:
为了减少代码冗余和文章篇幅,命名和打印不规则问题请忽略
Process 0:n=5756690257,id(n)=140103573185600Process 2:n=10819616173,id(n)=140103573185600Process 1:n=11829507727,id(n)=140103573185600Process 4:n=17812587459,id(n)=140103573072912Process 3:n=14424763612,id(n)=140103573185600Main:n=17812587459,id(n)=140103573072912Total time:0.1056210994720459- n是全局变量,Main的打印结果与线程相等,证明了线程之间是数据共享
但是,为什么多线程运行时间比多进程还要长?这与我们上面所说(线程的开销<<进程的开销)的严重不相符啊 。这就是轮到Cpython(python默认的解释器)中GIL(Global Interpreter Lock,全局解释锁)登场了 。
1、什么是GILGIL来源于Python设计之初的考虑,为了数据安全(由于内存管理机制中采用引用计数)所做的决定 。某个线程想要执行,必须先拿到 GIL 。因此,可以把 GIL 看作是“通行证”,并且在一个 Python进程中,GIL 只有一个,拿不到通行证的线程,就不允许进入 CPU 执行 。
Cpython解释器在内存管理中采用引用计数,当对象的引用次数为0时,会将对象当作垃圾进行回收 。设想这样一种场景:
一个进程中含有两个线程,分别为线程0和线程1,两个线程全都引用对象a 。当两个线程同时对a发生引用(并未修改,不需要使用同步性原语),就会发生同时修改对象a的引用计数器,造成计数器引用少于实质性的引用,当进行垃圾回收时,造成错误异常 。因此,需要一把全局锁(即为GIL)来保证对象引用计数的正确性和安全性 。无论是单核还是多核,一个进程永远只能同时执行一个线程(拿到 GIL 的线程才能执行,如下图所示),这就是为什么在多核CPU上,Python 的多线程效率并不高的根本原因 。

文章插图
那是不是在Python中遇到并发的需求就使用多进程就万事大吉了呢?其实不然,软件工程中有一句名言:没有银弹!
2、何时用?常见的应用场景不外乎三种:
- CPU密集型:程序需要占用CPU进行大量的运算和数据处理;
- I/O密集型:程序中需要频繁的进行I/O操作;例如网络中socket数据传输和读取等;
- CPU密集+I/O密集:以上两种的结合
CPU密集型的情况可以对比以上multiprocessing和threading的例子,多进程的性能 > 多线程的性能 。下面主要解释一下I/O密集型的情况 。与I/O设备交互,目前最常用的解决方案就是DMA 。
3、什么是DMADMA(Direct Memory Access)是系统中的一个特殊设备,它可以协调完成内存到设备间的数据传输,中间过程不需要CPU介入 。
以文件写入为例:
- 进程p1发出数据写入磁盘文件的请求
- CPU处理写入请求,通过编程告诉DMA引擎数据在内存的位置,要写入数据的大小以及目标设备等信息
- CPU处理其他进程p2的请求,DMA负责将内存数据写入到设备中
- DMA完成数据传输,中断CPU
- CPU从p2上下文切换到p1,继续执行p1

文章插图

文章插图
Python多线程的表现(I/O密集型)
推荐阅读
- 梦幻西游5开最好的组合是什么?
- 世界十大猛犬排名是怎样的?
- 智慧团建怎么转团关系?
- 专升本条件要求是什么?
- 可能存在生命的星系 星球本身是生命体
- 太阳将在约50亿年后成为什么 太阳将在约50亿年后成为哪一种星体
- 人有阴阳眼是真的吗? 阴阳眼能看到什么
- 金星为什么被称为金星 金星有生命信号
- 喝老寿眉的好处有哪些,有什么适合年轻人喝的茶
- 菊普什么人不能喝,紫罗兰花茶什么人不能喝
