多线程与多进程

注:本文是廖大的教程文章,本人也在学习,因为老是记不住,自己手打一边,代码也是亲自测试。
廖大传送门

多进程和多线程是实现多任务的常用两种方式。现在比较一下这两种方式。
首先要实现一个多任务,通常我们会设计一个 Master-Worker 模式,Master 负责分配任务,Worker 负责执行任务。因此,在多任务中,通常是有一个 Master,多个 Worker。

多进程

如果用多进程实现 Master-Worker ,主进程就是 Master ,其他进程就是 Worker。

多进程最大的优点就是稳定性高,因为一个子进程崩溃了,不会影响主进程和其他子进程。(当然主进程挂了,所有的子进程就也挂了,但是通常 Master 只负责分配任务,挂掉的几率很低。)著名的 Apache 最早就是采用多进程模式。

多进程最大的缺点是创建进程的代价大,在 Unix/Linux 系统下,用 fork 调用还行,在 Windows 下创建进程开销巨大。另外,操作系统能同时运行的进程也是有限的,在内存和 CPU 的限制下,如果有几千个进程同时运行,操作系统连调度都成问题。

如果用多线程实现 Master-Worker ,主线程就是 Master ,其他线程就是 Worker。
多线程模式通常比多进程要快一些,但也快不到哪去,而且,多线程的致命缺点是任何一个线程挂掉都可能直接造成整个进程崩溃,因为所有的线程共享进程的内存,。在 Windows 上,如果一个线程出现问题,你经常看到这样的提示,「该程序执行了非法操作,即将关闭」,其实是某个线程出现问题,但是操作系统会关闭整个进程。

在 Windows 下,多线程比多进程效率高,所以微软的 IIS 服务器默认采用多线程的模式,由于多线程存在稳定性的问题,所以 IIS 的稳定性就不如 Apache 为了缓解这个问题,IIS 和 Apache 现在又有多线程加多进程的模式,这个不懂,据说问题越高越复杂。

线程切换

无论多线程还是多进程,数量一多,效率肯定上不去,为什么?
举个例子
假如你不幸假设你不幸正在准备中考,每天晚上需要做语文、数学、英语、物理、化学这5科的作业,每项作业耗时1小时。

如果你先花1小时做语文作业,做完了,再花1小时做数学作业,这样,依次全部做完,一共花5小时,这种方式称为单任务模型,或者批处理任务模型。

假设你打算切换到多任务模型,可以先做1分钟语文,再切换到数学作业,做1分钟,再切换到英语,以此类推,只要切换速度足够快,这种方式就和单核CPU执行多任务是一样的了,以幼儿园小朋友的眼光来看,你就正在同时写5科作业。

但是,切换作业是有代价的,比如从语文切到数学,要先收拾桌子上的语文书本、钢笔(这叫保存现场),然后,打开数学课本、找出圆规直尺(这叫准备新环境),才能开始做数学作业。操作系统在切换进程或者线程时也是一样的,它需要先保存当前执行的现场环境(CPU寄存器状态、内存页等),然后,把新任务的执行环境准备好(恢复上次的寄存器状态,切换内存页等),才能开始执行。这个切换过程虽然很快,但是也需要耗费时间。如果有几千个任务同时进行,操作系统可能就主要忙着切换任务,根本没有多少时间去执行任务了,这种情况最常见的就是硬盘狂响,点窗口无反应,系统处于假死状态。

所以,多任务一旦多到一个限度,就会消耗掉系统所有的资源,结果效率急剧下降,所有任务都做不好。

计算密集型 vs IO密集型

是否采用多任务的的第二个考虑因素是任务的类型,我们可以把任务分为计算密集型和IO密集型
1、计算密集型的特点是要进行大量的计算,消耗 CPU 的资源,比如计算圆周率,视频的解码等,全靠 CPU 的运算能力。这种计算密集型任务虽然也可以用多任务完成,但是任务越多,花在任务切换的时间就越多,CPU 执行效率就会降低,所以要想高效利用 CPU 计算密集型任务同时进行的数量应当等于 CPU 的核心数。

计算密集型任务主要消耗 CPU 资源,因此,代码运行速度至关重要,python这种脚本语言执行效率很低自然没办法胜任。对于计算密集型任务,最好才用 C 编写。

2、IO 密集型任务,涉及到网络,磁盘 IO 的任务都是 IO密集型任务,这类任务的特点是 CPU 消耗很少,任务的大部分时间都在等 IO 操作完成,「因为 IO 的速度远远低于内存和 CPU 的速度」对于IO密集型任务,任务越多,CPU效率越高,但也有一个限度。常见的大部分任务都是IO密集型任务,比如Web应用。

IO密集型任务执行期间,99%的时间都花在IO上,花在CPU上的时间很少,因此,用运行速度极快的C语言替换用Python这样运行速度极低的脚本语言,完全无法提升运行效率。对于IO密集型任务,最合适的语言就是开发效率最高(代码量最少)的语言,脚本语言是首选,C语言最差。

异步IO

考虑到CPU和IO之间巨大的速度差异,一个任务在执行的过程中大部分时间都在等待IO操作,单进程单线程模型会导致别的任务无法并行执行,因此,我们才需要多进程模型或者多线程模型来支持多任务并发执行。

现代操作系统对IO操作已经做了巨大的改进,最大的特点就是支持异步IO。如果充分利用操作系统提供的异步IO支持,就可以用单进程单线程模型来执行多任务,这种全新的模型称为事件驱动模型,Nginx就是支持异步IO的Web服务器,它在单核CPU上采用单进程模型就可以高效地支持多任务。在多核CPU上,可以运行多个进程(数量与CPU核心数相同),充分利用多核CPU。由于系统总的进程数量十分有限,因此操作系统调度非常高效。用异步IO编程模型来实现多任务是一个主要的趋势。

对应到Python语言,单线程的异步编程模型称为协程,有了协程的支持,就可以基于事件驱动编写高效的多任务程序。

注意了啊,敲黑板啦 !!!
前面学习的多进程和多线程大部分情况下都是扯淡的,请以后认真学习异步IO(协程)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值