首先,阮一峰《进程与线程的一个简单解释》一文中形象生动地将计算机 CPU 比做一个工厂,进程相当于工厂内不同车间,线程相当于车间内不同协作的工人。
工厂电力有限,一次只能一个车间开工:单个CPU一次只能运行一个进程,其他进程处于非运行状态。
一个车间里可以有很多工人协同工作:一个进程可以包括多个线程协同进行。
车间空间由工人们共享:一个进程的内存空间是每个线程共享的。
车间内每间房间的大小不同,里面人满的时候,其他人就不能进去了:某些线程使用某些共享内存时,若线程数目超出限制,则其他线程必须等其中线程结束,才能使用这一块内存。
为了控制房间不超出人数限制,就在门口挂一定数量的钥匙,进去的人取一把,出来时放回原处,后到的人若取不到钥匙就在门口排队:该做法叫做“信号量”(Semaphore),用来保证多个线程不会互相冲突,即控制多个线程同时读写某一块内存区域。
操作系统的设计可以归纳为三点:
该部分来源于知乎问题“线程和进程的区别是什么?”中作者 zhonyong 的高赞回答。
进程和线程都是一个 CPU 工作时间段的描述,颗粒大小不同。
执行一段程序代码,除了CPU以外所有的就构成了这个程序的执行环境,也就是我们所定义的程序上下文。当这个程序执行完了,或者分配给他的CPU执行时间用完了,那它就要被切换出去,在被切换出去的最后一步工作就是保存程序上下文,因为这个是下次他被 CPU 执行的运行环境,必须保存。
在CPU看来所有的任务都是一个一个的轮流执行的,具体的轮流方法就是:先加载程序A的上下文,然后开始执行A,保存程序A的上下文,调入下一个要执行的程序B的程序上下文,然后开始执行B,保存程序B的上下文。
进程就是包含上下文切换的程序执行时间总和 = CPU加载上下文+CPU执行+CPU保存上下文
进程的颗粒度太大,每次都要有上下的调入,保存,调出。如果我们把进程比喻为一个运行在电脑上的软件,那么一个软件的执行不可能是一条逻辑执行的,必定有多个分支和多个程序段,就好比要实现程序A,实际分成 a,b,c等多个块组合而成。
那么这里具体的执行就可能变成:程序A得到CPU =》CPU加载上下文,开始执行程序A的a小段,然后执行A的b小段,然后再执行A的c小段,最后CPU保存A的上下文。
这里a,b,c的执行是共享了A的上下文,CPU在执行的时候没有进行上下文切换的。这里的a,b,c就是线程,也就是说线程是共享了进程的上下文环境的、更为细小的CPU时间段
该部分来源于《程序员的自我修养(二):操作系统、进程与线程》一文。
在操作系统中执行的程序,都以进程的方式运行在更低的权限中。事实上,操作系统是以进程为单位去分配空间和执行的。但是,进程和程序有什么不同呢?
我们说程序是一组指令的集合,它静态存储于诸如磁盘之类的存储器里;当一个程序被操作系统执行时,它就会被载入内存空间,并在逻辑上产生一个独立的实例,这就是进程。
这就好像是说,程序是一道菜谱,其中的指令,就是指挥你开火加盐的步骤;进程则是烹饪的过程,操作系统按照指令一丝不苟地烹饪,得到的结果就是我们的菜肴。
随着 CPU 频率增长逐渐停滞,CPU 开始向多核的方向发展。为了让多个 CPU 核心同时为我们工作,并行地执行任务,就需要涉及线程的概念。线程的英文是 Thread,有时也称为轻量级进程 (Lightweight Process),它是操作系统进行任务调度的最小单元。线程存活于进程之中;同一个进程中的线程,共享一个虚拟内存空间,以及其中的资源;线程之间各自持有自己的线程 ID、当前指令的指针(PC)、寄存器集合以及栈。
该部分来源于知乎问题“线程和进程的区别是什么?”中 宇宙之一粟 的回答。
进程是资源(CPU、内存等)分配的基本单位,具有一定功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位。
线程是进程的一个实体,是独立运行和独立调度的基本单位(CPU上真正运行的是线程)。线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),但是它可与同属一个进程的其他的线程共享进程所拥有的全部资源。
二者的区别:
二者优劣比较:
口语表述:
进程的本质::正在执行的一个程序,可以进程比作一个容器或者工厂
线程的本质:真正运行的是一个一个的线程
线程包含:
通信是人的基本需求,进程与进程之间是相互独立的,也有通信需求。根据这一问题就可以展开内容提问:进程/线程如何通信?
答:进程可以通过管道、套接字、信号交互、共享内存、消息队列等等进行通信;而线程本身就会共享内存,指针指向同一个内容,交互很容易。
一旦有了通信,进程就会产生矛盾。这些矛盾就会体现在如何同步上。在单个CPU下,实际上在任何时刻只能有一个进程处于执行状态。而其他进程则处于非执行状态。我们是如何确定在任意时刻到底由哪个进程执行,哪些不执行呢?(如何进行进程调度?)线程之间的关系是合作关系。既然是合作,那就得有某种约定的规则,否则合作就会出问题。(如何进行线程同步?)
还有内存问题,进程要分配内存,所以开销很大;线程只需要分配栈,分配一个PC(程序计数器)就好,内存开销小。