多进程和多线程主要区别是:线程是进程的子集,一个进程可能由多个线程组成。多进程的数据是分开的、共享复杂,需要用IPC(Inter-Process Communication:进程间通信),但同步简单;多线程共享进程数据、共享简单,但同步复杂。
1.多进程的优缺点分析
多进程优点: 1. 每个进程相互独立,稳定性高,因为一个子进程崩溃了,不会影响主进程和其他子进程。 2. 通过增加CPU,就可以扩充性能; 3. 可以尽量减少线程加锁/解锁的影响,极大提高性能,就算是线程运行的模块算法效率低也没关系; 4. 每个子进程都有2GB地址空间和相关资源,总体能够达到的性能上限非常大。
多进程缺点:
2.多线程的优缺点分析
多线程的优点: 1. 线程间通信更加灵活。 2. 线程的创建和销毁成本比较低。 3. 线程间的切换调度成本更加低。
多线程的缺点: 1. 多线程模式致命的缺点就是任何一个线程挂掉都可能直接造成整个进程崩溃,因为所有线程共享进程的内存。 2. 每个线程与主程序公用地址空间,受限于2GB地址空间; 3. 线程之间的同步和加锁控制比较麻烦; 4. 到达一定的线程数量后,即使再增加CPU也无法提高性能,因为线程多了之后,线程本身的调度也是一个麻烦事儿,需要消耗更多的CPU资源
3.多进程与多线程的使用场景
多进程应用场景 - nginx主流的工作模式是多进程模式(也支持多线程模型) - 几乎所有的web server服务器服务都有多进程的,至少有一个守护进程配合一个worker进程,例如apached,httpd等等以d结尾的进程包括init.d本身就是0级总进程,所有你认知的进程都是它的子进程; - chrome浏览器也是多进程方式。 - redis也可以归类到“多进程单线程”模型(平时工作是单个进程,涉及到耗时操作如持久化或aof重写时会用到多个进程)
多线程应用场景 - 线程间有数据共享,并且数据是需要修改的(不同任务间需要大量共享数据或频繁通信时)。 - 提供非均质的服务(有优先级任务处理)事件响应有优先级。 - 单任务并行计算,在非CPU Bound的场景下提高响应速度,降低时延。 - 与人有IO交互的应用,良好的用户体验(键盘鼠标的输入,立刻响应)
4.计算密集型 vs. IO密集型
无论是多进程还是多线程目的都是为了完成多任务,多任务又分为计算密集型和IO密集型。
计算密集型任务的特点是要进行大量的计算,消耗CPU资源,比如计算圆周率、对视频进行高清解码等等,全靠CPU的运算能力。这种计算密集型任务虽然也可以用多任务完成,但是任务越多,花在任务切换的时间就越多,CPU执行任务的效率就越低,所以,要最高效地利用CPU,计算密集型任务同时进行的数量应当等于CPU的核心数。
计算密集型任务由于主要消耗CPU资源,因此,代码运行效率至关重要。Python这样的脚本语言运行效率很低,完全不适合计算密集型任务。对于计算密集型任务,最好用C语言编写。
IO密集型任务,涉及到网络、磁盘IO的任务都是IO密集型任务,这类任务的特点是CPU消耗很少,任务的大部分时间都在等待IO操作完成(因为IO的速度远远低于CPU和内存的速度)。对于IO密集型任务,任务越多,CPU效率越高,但也有一个限度。常见的大部分任务都是IO密集型任务,比如Web应用。
IO密集型任务执行期间,99%的时间都花在IO上,花在CPU上的时间很少,因此,用运行速度极快的C语言替换用Python这样运行速度极低的脚本语言,完全无法提升运行效率。对于IO密集型任务,最合适的语言就是开发效率最高(代码量最少)的语言,脚本语言是首选,C语言最差。
5.异步IO
考虑到CPU和IO之间巨大的速度差异,一个任务在执行的过程中大部分时间都在等待IO操作,单进程单线程模型会导致别的任务无法并行执行,因此,我们才需要多进程模型或者多线程模型来支持多任务并发执行。
现代操作系统对IO操作已经做了巨大的改进,最大的特点就是支持异步IO。如果充分利用操作系统提供的异步IO支持,就可以用单进程单线程模型来执行多任务,这种全新的模型称为事件驱动模型,Nginx就是支持异步IO的Web服务器,它在单核CPU上采用单进程模型就可以高效地支持多任务。在多核CPU上,可以运行多个进程(数量与CPU核心数相同),充分利用多核CPU。由于系统总的进程数量十分有限,因此操作系统调度非常高效。用异步IO编程模型来实现多任务是一个主要的趋势。
对应到Python语言,单线程的异步编程模型称为协程,有了协程的支持,就可以基于事件驱动编写高效的多任务程序。