进程、线程对比
- 进程,能够完成多任务,比如 在一台电脑上能够同时运行多个 QQ
- 线程,能够完成多任务,比如 一个 QQ 中的多个聊天窗口
进程是系统进行资源分配和调度的一个独立单位.
线程是进程的一个实体,是 CPU 调度和分派的基本单位,它是比进程更小的能独立运行的基本单位.线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源( 如程序计数器,一组寄存器和栈),但是它可与同属一个进程的其他的线程共享进程所拥有的全部资源.
区别
一个程序至少有一个进程,一个进程至少有一个线程.
线程的划分尺度小于进程(资源比进程少),使得多线程程序的并发性高。
进程在执行过程中拥有独立的内存单元,而多个线程共享内存,从而极大地提高了程序的运行效率
线程不能够独立执行,必须依存在进程中
优缺点
线程和进程在使用上各有优缺点:线程执行开销小,但不利于资源的管理和保护;而进程正相反。
关于多进程和多线程,教科书上最经典的一句话是“进程是资源分配的最小单位,线程是 CPU 调度的最小单位”。这句话应付考试基本上够了,但如果在工作中遇到类似的选择问题,那就没有那么简单了,选的不好,会让你深受其害。所以他也是面试者最喜欢考察的题目之一。
我们按照多个不同的维度,来看看多进程和多线程的对比(注:都是相对的,不是说一个好得不得了,另一个差的无法忍受)
维度 | 多进程 | 多线程 | 总结 |
---|---|---|---|
数据共享、同步 | 数据是分开的:共享复杂,需要用IPC;同步简单 | 多线程共享进程数据:共享简单;同步复杂 | 各有优势 |
内存、CPU | 占用内存多,切换复杂,CPU利用率低 | 占用内存少,切换简单,CPU利用率高 | 线程占优 |
创建销毁、切换 | 创建销毁、切换复杂,速度慢 | 创建销毁、切换简单,速度快 | 线程占优 |
编程调试 | 编程简单,调试简单 | 编程复杂,调试复杂 | 进程占优 |
可靠性 | 进程间不会相互影响 | 一个线程挂掉将导致整个进程挂掉 | 进程占优 |
分布式 | 适应于多核、多机分布 ;如果一台机器不够,扩展到多台机器比较简单 | 适应于多核分布 | 进程占优 |
然后我们来看下线程和进程间的比较
多进程 | 多线程 | |
---|---|---|
优点 | 内存隔离,单进程已成不会导致整个应用崩溃。方便调试 | 提高系统的并发性,并且开销小 |
缺点 | 进程间调用,通讯和切换开销均比多线程大 | 没有内存隔离,单线程的崩溃会导致整个应用的推出,发生内存bug时,定位及其不方便(回调噩梦) |
使用场景 | 目标子功能交互少,如果资源和性能许可,请设计由多个子应用程序来组合完成。 | 存在大量IO、网络等耗时操作,或需要与用户交互时,使用多线程有利于提高系统的并行性和用户界面交互的体验。 |
需要频繁创建销毁的优先用线程。
实例:web 服务器。来一个建立一个线程,断了就销毁线程。要是用进程,创建和销毁的代价是很难承受的。
需要进行大量计算的优先使用进程。
所谓大量计算,当然就是要消耗很多 cpu,切换频繁了,这种情况先线程是最合适的。
实例:图像处理、算法处理
强相关的处理用线程,弱相关的处理用进程。
什么叫强相关、弱相关?理论上很难定义,给个简单的例子就明白了。
一般的 server 需要完成如下任务:消息收发和消息处理。消息收发和消息处理就是弱相关的任务,而消息处理里面可能又分为消息解码、业务处理,这两个任务相对来说相关性就要强多了。因此消息收发和消息处理可以分进程设计,消息解码和业务处理可以分线程设计。
可能扩展到多机分布的用进程,多核分布的用线程。
都满足需求的情况下,用你最熟悉、最拿手的方式。
至于”数据共享、同步“、“编程、调试”、“可靠性”这几个维度的所谓的“复杂、简单”应该怎么取舍,只能说:没有明确的选择方法。一般有一个选择原则:如果多进程和多线程都能够满足要求,那么选择你最熟悉、最拿手的那个。
关系对比
- 线程是依附在进程里面的,没有进程就没有线程。
- 一个进程默认提供一条线程,进程可以创建多个线程。
优缺点对比
进程优缺点:
- 优点:可以用多核
- 缺点:资源开销大
线程优缺点:
- 优点:资源开销小
- 缺点:不能使用多核
要点总结
- 进程和线程都是完成多任务的一种方式
- 多进程要比多线程消耗的资源多,但是多进程开发比单进程多线程开发稳定性要强,某个进程挂掉不会影响其它进程。
- 多进程可以使用cpu的多核运行,多线程可以共享全局变量。
- 线程不能单独执行必须依附在进程里面
概念问题(面试常问)
在计算机中,如果你的程序在等待,通常是因为以下两个原因。
- I/O 限制:这个限制很常见。计算机的 CPU 速度非常快——比计算机内存快几百倍,比硬盘或者网络快几千倍。
- CPU 限制:在处理数字运算任务时,比如科学计算或者图形计算,很容易遇到这个限制。
以下是和并发相关的两个术语。
- 同步:一件事接着一件事发生,就像送葬队伍一样。
- 异步:任务是互相独立的,就像派对参与者从不同的车上下来一样
当你要用简单的系统和任务来处理现实中的问题时,迟早需要处理并发。假设你有一个网站,必须给用户很快地返回静态和动态网页。一秒是可以接受的,但是如果展示或者交互需要很长时间,用户就会失去耐心。谷歌和亚马逊的测试显示,页面加载速度降低一点就会导致流量大幅下降。
但是,如何处理需要长时间执行的任务呢,比如上传文件、改变图片大小或者查询数据库?显然无法用同步的 Web 客户端代码解决这个问题,因为同步就必然会产生等待。
在一台电脑中,如果你想尽快处理多个任务,就需要让它们互相独立。慢任务不应该阻塞其他任务。
并发(concurrency)和并行(parallellism)是
- 并发:一件事情由多个人同时去做(多线程)
- 并行:多个人同时做多件事情(多进程)
多进程模块,让我们可以不受 GIL 的限制,大大缩短执行时间。