这实在是一个过于经典的面试题,尤其是对于go开发者来说,毕竟go有协程这种杀手级的东西,面试官就更爱问这个问题了
同时网上相关资料很杂,本身这种抽象概念的理解就没有绝对的标准表达,大家领会意思就够了,哈哈,但带来的问题就是查找相关资料的时候容易把自己越看越乱
所以此处我写的内容,也是我自己的理解,有不同理解的欢迎讨论
进程
进程,就是我们跑起来的程序,在系统中的抽象
我们的程序,他不跑的时候,就是可执行文件,在linux上可能没有扩展名,在windows上那就是.exe,总而言之,他就是我们机器上的一个文件
而当我们将他跑起来的时候,他会申请内存空间,会占据一定的资源, 会做各种各样的事情……总之他跑起来了,就不是死的文件了,这个时候,他在系统中的抽象,就是进程
理解了上面的概念,才有别的概念:
- 两个进程的内存空间是互不干涉的,因为两个进程那就是两个程序了,当然不能干涉了
- 因为两个进程的内存空间互不干涉这个点,所以在系统上资源分配的最小单位是进程
线程
线程这个词其实是有一定歧义的,简单来说在软件概念中有一个线程,在硬件概念中也有一个线程,我曾经5次在面试遇到这个问题时用硬件概念中的物理线程去回答面试官,没有一个面试官觉得哪里有问题,哈哈哈哈哈哈哈
物理线程
就是我们说,cpu 4核心8线程,8核心8线程,8核心16线程的那个线程,是实际存在于我们cpu中的硬件,而非抽象概念,你乐意的话可以自己买个cpu,撬开盖板看一眼
物理线程是我们cpu实际上执行逻辑的硬件,一个线程同一时间只能跑一个法律咨询逻辑,所以cpu有几个物理线程,服务器就能同时【真正的同时】跑多少个逻辑,这是硬的物理上限,真正的【并行】
可以理解为cpu有几线程,就是cpu里有几台计算器,跑逻辑就是在计算器上进行计算,如果cpu有8个线程,那同一时间就是最多同时计算8道题,不可能再多
另外,我们要跑的逻辑,也必须在物理线程上去跑,所以物理线程,就是我们实际用于执行逻辑的硬件
逻辑线程
逻辑线程,就是程序具体需要执行的逻辑,在系统中的抽象
上面说过,进程是我们跑起来的程序的抽象,那一个程序跑起来,他肯定有自己要执行的逻辑,他要执行的逻辑的抽象,就是线程。
一个程序,他可以是单线程,也可以是多线程,这取决于程序本身,但是否多线程,都不影响这个跑着的程序本身在系统中被抽象为一个进程这件事。
有了上面的概念,然后才是其他的概念:
- 因为多线程也是归属于跑着的程序,也就是归属于进程,所以同进程下的多个线程是共享进程的内存空间的
- 因为线程是具体要执行的逻辑,所以cpu调度的最小单位是线程
- 所以cpu时间片切换,真正在切换的是线程
进程与线程
上面更多在介绍【进程是什么】【线程是什么】这样概念性的东西
关于线程与进程的关系或者说区别,我看到了一个非常好的表述,这里也记录一下,以下表述来自于参考文档
做个简单的比喻:进程=火车,线程=车厢
- 线程在进程下行进(单纯的车厢无法运行)
- 一个进程可以包含多个线程(一辆火车可以有多个车厢)
- 不同进程间数据很难共享(一辆火车上的乘客很难换到另外一辆火车,比如站点换乘)
- 同一进程下不同线程间数据很易共享(A车厢换到B车厢很容易)
- 进程要比线程消耗更多的计算机资源(采用多列火车相比多个车厢更耗资源)
- 进程间不会相互影响,一个线程挂掉将导致整个进程挂掉(大部分情况下,java有特例)(一列火车不会影响到另外一列火车,但是如果一列火车上中间的一节车厢着火了,将影响到所有车厢)
- 进程可以拓展到多机,进程最多适合多核(不同火车可以开在多个轨道上,同一火车的车厢不能在行进的不同的轨道上)
- 进程使用的内存地址可以上锁,即一个线程使用某些共享内存时,其他线程必须等它结束,才能使用这一块内存。(比如火车上的洗手间)-"互斥锁"
- 进程使用的内存地址可以限定使用量(比如火车上的餐厅,最多只允许多少人进入,如果满了需要在门口等,等有人出来了才能进去)-“信号量”
协程
协程就是程序自己管理的线程
以go来举例,协程就是go语言中抽象出来的GMP中的G,他的调度由go的runtime/www.237fa.com自己控制,和cpu对线程的切换一样,也存在不同协程间的切换。
在理解了线程之后,就会觉得协程的概念基本就是套娃,往里再套一层
标签:逻辑,协程,火车,线程,进程,cpu From: https://www.cnblogs.com/77cxw/p/17978096