面试官:请说一下进程和线程的区别。
我:这个我知道,进程和线程都是一个时间段的描述,是CPU工作时间段的描述。进程是资源分配的基本单位,线程是程序执行的基本单位。
面试官:那能说一下资源分配和执行的过程吗?
我:这个...
面试官:没事,今天面试就到这里。回去等通知吧。
我:(送分题答成送命题)
小伙伴们是否会经常混淆进程和线程的概念呢?
今天就和大家聊一下进程和线程的概念和CPU是如何切换进程和线程的。
前提知识
一台(单核CPU)电脑或者一部(单核CPU)手机里会同时运行很多程序,就像你可以一边上视频网站,一边聊微信一样。
但这些程序并不是真的都在“同时”运行,而是队轮流借用CPU的计算能力来依次执行。
但是CPU切换程序的速度太太太太太快了所以人是根本察觉不到的。
进程
进程是资源分配的基本单位
这句话怎么理解呢? 我们可以把正在运行的每个程序看作一个进程,这个进程需要借用CPU的运算能力、内存容量、全局变量等才可以进行运算。当我们分配资源的时候必须是以一个进程为单位,不会说分配给0.5或者1.5个进程资源。
例如我要打开微信和迅雷,肯定是一次性加载完微信进程->开始运算->加载迅雷进程,而不会出现加载了半个微信进程 + 半个迅雷进程的情况。
进程的切换
用户态与内核态
为了给进程分配资源,我们需要进行系统调用,去向更高一级的权限申请这些资源。
我们的操作系统将权限分成2大类
用户态:拥有控制计算机一部分资源的权利。无法直接调用CPU、內存、磁盘空间、网络、硬件等資源。需要通过内核态去调用。
内核态:拥有控制计算机全部资源的权利。并且能够合理执行用户态的调用请求。
举个例子,用户想要打开微信会是什么过程呢?
用户态:我要运算微信程序,我需要用CPU,200KB内存,1MB磁盘空间。
内核态:收到!
内核态开始调用所需要的资源
内核态:先给你200ms的CPU计算时间,200K内存,1MB磁盘空间。过了200m我要用CPU跑别的程序了。
用户态拿到资源开始运行程序。可以是从头开始运行程序,也可以继续执行上下文中的指令(上一次执行中断的地方)。
200ms后
内核态保存进程上下文,加载下一个进程的上下文,准备将计算资源分配给下一个进程。

为什么要搞的这么麻烦呢?
因为要让用户直接调用资源太危险了。试想一下一个普通程序员为了执行一段代码需要从头写一个内存管理程序是多么令人头疼的事情。
上面的例子出现了两种类型的切换
- 用户态与内核态的切换。想要更深入理解的同学,推荐去看这篇文章。一文让你明白CPU上下文切换
- 内核态中进程与进程间的切换。(这是我主要想讨论的)
切换进程的目的
确保所有进程可以有效的执行,不会因为一个进程迟迟没有结束拖慢整个计算机。
从一个进程切换到另一个进程会用到哪些资源?
- 虚拟地址空间
- 可执行代码
- 安全的上下文
- 唯一的进程标识
- 环境变量
- 系统对象的引用、文件、设备、socket、窗口
切换进程的开销
进程越多,内核态为了确保每个进程都有运行的机会自然会频繁的切换进程。
但是切换的过程也是需要花费时间的。进程越多消耗在这个过程的时间也越多。
最终会导致执行效率的下降。
线程
线程是程序执行的基本单位
进程已经拿到了计算资源,第二步就是执行具体的任务了。哪个线程执行哪个任务完全由用户的代码决定。
例如:我可以用多线程来计算1到10000的和,也可以用单线程执行一段排序算法。
所有线程共享进程所拥有的全部资源。
线程的切换
线程的切换过程与进程的切换过程类似。但是有一些共享资源是不用切换或者说重新分配的。
例如虚拟内存。切换线程的开销主要在线程的数据、寄存器等不共享的资源。
参考资料
一文让你明白CPU上下文切换
线程和进程的区别是什么? - 无与童比的回答 - 知乎
线程和进程的区别是什么? - zhonyong的回答 - 知乎