如何理解线程与进程(含有通俗解释)

1.线程与进程:

        线程和进程应该是学计算机的朋友听的比较多的词汇了,其实就算不学习计算机,懂电脑的朋友也可能有点印象,因为我们的CPU经常说到8和16线程什么的,仿佛线程越多代表CPU性能越强悍,那么线程和进程到底是什么呢?我将结合近期学习内容以及自己的理解整理解释一下,线程与进程。

        首先,我想先讲讲进程,相当于线程来说,我觉得进程相对没有那么抽象,更容易理解,其实进程就是相当于我们玩的游戏,或者我们用到的工具,绝地求生ing,英雄联盟ing,腾讯会议ing,这里我为什么要加ing,在因为其实严格意义来说刚刚提到的这几个都算是程序,程序和进程之间的关系是什么呢?进程是依赖于程序的运行而存在的,可以理解成当程序运行时的状态就是进程,换而言之就是程序是静态的,进程是动态的,当我们一个软件或者游戏运行起来了,对于计算机来说,我们就开启了一个进程,这个就是进程,下面会提出进程的一下特征以及定义等概念,①进程是操作系统进行资源分配和调度的一个独立单位,②每个进程都拥有独立的地址空间,地址空间包括代码区、数据区和堆栈区,进程之间的空间是隔离的,互不影响。

        这里抛出了概念,接下来我会对概念进行自己的解释(可能存在错误,非常感谢指出),针对①,进程是操作系统调度和分配的一个独立单位,操作系统就是我们平时用的windows,这就是我们平时用的系统,系统可以调配一个主机所有东西,包括CPU、内存、显卡、运存等等,操作系统的优点就是将一下复杂的操作进行了可视化处理(这里做点简单的例子,比如我们进入一个文件夹,在操作系统的帮助下,你只需要双击即可进入,但是如果站在程序员角度,需要在cmd工具栏中,输入cd desktop这种命令,看起来就是一堆代码行不好理解,其实cmd工具栏也是一个可视化工具了,正在纯命令行操作和在cmd中的操作非常相似,没什么可视化的反馈给你,只有数据,所以操作系统非常强大,因为有他的存在,降低了我们学习计算机的难度,更便捷的使用计算机了。)

        大伙应该都觉得可视化的东西操作起来更简单把,不然也不会经常说啥啥很抽象,而这里就能看出进程需要调度的东西其实是比较多的,因为操作系统在我们电脑里面层级已经非常高了,相当于总统给你布置任务,可想而知进程的任务也不轻松,接下里我站在不了解计算机的角度类比一下,我们把计算机类比成一个国家,进程就相当于供电局、供水局、公安局、宣传局等等,由此其实可以看出,在理想状态下,一个国家分成非常多的进程执行下来,有条不紊的话,再艰难的任务也会变得轻松许多,这里将进程比喻成这些了,那么国家就是操作系统,国家在会为每个不同的部门分配场地,这就是计算机中的内存地址,各自在各自的场地中工作,相互不会干扰和影响,平时国家就根据每个部门的需要为他们分配资源,比如人力物力和土地等等,这样这些部门就能有条不紊的运行下去,就像我们计算机中的进程一样,同样可以将进程理解成一个大的项目工程,当然小的也算,比如一个制造车子的流水线也能叫做一个进程,但是需要根据调度者来决定,比如对于一个国家来说,一个车子的流水线肯定不算一个进程,很明显国家不会去关心一个流水线的工作状态,也无暇关注,但是对于这个车间的主管来说,这就是一个进程,因为其中的各个环节他是可以调度分配资源的,比如哪里需要加派人手等等,这样讲大家应该都明白什么是进程了,等介绍完线程我会再对比他们的区别加深记忆,现在先认识什么是进程,这里为大家展示一个图片(他人制作),稍后我会挂出他的出处,对了忘记补充进程的定义了,这是进程的定义:

进程是一个具有一定独立功能的程序在一个数据集合上依次动态执行的过程。进程是一个正在执行的程序的实例,包括程序计数器、寄存器和程序变量的当前值。

在这里插入图片描述

那么什么是线程呢?

由于进程的创建、销毁与切换存在较大的开销,那么就需要一种更轻便的进程技术,于是80年代,线程的概念就开始出现,其实从名字就能听出来大概了,线程被设计成进程的一个执行路径,同一个进程中的线程共享进程的资源,对于系统来说对于线程的调度所需的成本要远远低于进程,这里通俗比喻就是,比如销售一个产品,从制作到包装到销售到发货到结算等等,都能一个人去完成,但是当任务量打起来后,一个人的处理速度是有限的,比如销售产品这整个过程是一个进程,如果一个人从头到尾自己一个人干,那么我们就可以说这是一个单线程进程,这样的结果很明显,工作效率很低,即便他是一个非常强大的人,环节之前的切换也会耗费很多精力,计算机来说就是性能,因为他在干一件事的时候,其他资源都在等待,比如他在打包的时候,剩下的产品都在等待他操作,而多线程相当于雇了很多工人,这些工人一起共享这个工作室,大家一起分工合作,分成ABCD等等工序,这样就大大降低了等待时间,节省了时间成本,这就是多线程的意义,可以简单理解成进程是产业链从开始到结束的全过程,而线程是各个工序,当然一个线程就能完成整个工序但是会浪费时间成本,所以多线程的优势非常明显,说到这里,肯定有很多人跟我想的一样觉得线程其实不就是进程一模一样嘛?但是其实两者还是存在差别的:

①从本质来讲,换我的话来讲就是从调度者来讲,进程是操作系统的资源分配的基本单位,而线程是处理器(CPU)任务调度和执行的基本单位,这里顺便和大家通俗解释一下CPU和操作系统的关系,CPU上可以执行所有程序,包括我们的操作系统也是我们在按照电脑的时候安装的程序,叫做windows系统,CPU可以赋予程序特权,而操作系统是程序中的王中王,他的权限非常高,可以调度电脑基本所有东西,操作系统甚至可以控制其他应用使用CPU的权限是多少,分配CPU的时间片,也能够管理磁盘。网络等等与CPU不直接相关的东西,保护计算机的安全,CPU就是一个公司的程序员综合(技术总和),操作系统就是CEO和执行董事,是一个公司的首脑,使得团队健康长远的发展。(PS:我一开始还以为操作系统是老大,是权限最高的,实际是CPU,只是CPU愿意信任操作系统,将最高特权给他了)

②包含关系:一个进程至少有一个线程,线程是进程的一部分,所以线程又称轻权进程或轻量级进程

③资源开销:每个进程都有独立的地址空间,进程之间的切换会有较大的开销,同一个进程内的线程共享进程地址空间,每个线程都有独立运行栈和程序计数器,切换开销小

④影响关系:由于③处可以看出,由于地址空间的区别,导致了他们的影响程度,进程崩溃的时候在操作系统的保护模式下其他进程不好被影响,但是如果一个线程崩溃了可能导致整个进程被操作系统终止,由此可以看出多进程的优势,但是考虑到开销也不能无线细化进程,线程也有他的优势,但是相较而言,多进程相对多线程更加健壮。

        这里顺便介绍两个新名词给出一个新的例子,在一个餐馆里面,服务员可以在不同客户之间交叉上菜或者接受点菜服务,这样一个服务员在不同客户之间切换就像不同线程在CPU之间切换一样,称之为并发,在后厨几个厨师在不同的锅炉前同时做菜,这个过程我们叫并行,其实从字面意思很容易理解,但是我们又引出一个新名词,就是像服务员这种工作类型我们称之为I/O密集型,相较于厨师而言,服务员大部分时间都耗费在命令的传递和餐品端出,这种行为我们就叫IO,也就是数据的存储和取出,相较于后厨而言,这种行为相对简单,不需要计算,需求基本产生于数据的读取和存储之间了,这种就叫I/O密集型,那么后厨这种会耗费大量时间在烹饪和调制的工作上的就叫CPU密集型,这种换做计算机语言来说,耗费了大量的时间在数据的计算和转换等等,逻辑判断等等上,就是需要计算的事情上,我们称之为CPU密集型,那么知道有这两种类型,他们区别在哪呢?他们的特点介绍完后,其实不难看出一个是时间大量耗费数据的读取和存储,一个是耗费在计算和数据处理了。那么依旧是比方,比如我一个餐馆,招聘了大量服务员,为每一桌食客都分配一个服务员进行个性化服务,但是我就在后排安排一个高端厨师,他厨艺高超以一敌十,但是实际结果可想而知,食客一定会等的不耐烦,因为后厨就一个人,肯定忙不过来,尽管他是一个厨艺高超的老师傅并且客厅里面有大量的服务员(线程)在给后厨菜单后浪费了大量的时间在等待,并且十分占用空间,所以这里就体现了线程的分配合理性,对于CPU计算机密集型,较多的线程可以提升性能(但是并不是越多越好,线程之前切换也是需要开销的,这就好比点了两个菜,你用了五个厨子来炒,还比上两个来的快。要根据应用的实际情况来定,一般线程数等于CPU核心数是较为合理的),而对于I/O密集型,我们更需要一个反应敏捷的服务员,由此可以看出线程的分配在进程的运行中起到了重要的作用,可以大大节省程序运行时间,由此也诞生了一点,我早有耳闻的一个问题,知道这些解释起来就很轻松了,我之前总是听说js写web应用会比java好点,就是因为web应用就是典型的I/O密集型,CPU主要的任务就放在了数据的请求展示(大部分其实是请求)和数据存贮上了,而js作为高效开发语言,本来相较于java和C就有较少代码体量并且本身是单线程的劣势也被磨平了,这里js就是我说的高级服务员,因为web应用大部分时间用在了IO上,所以相对java这种多线程语言,js也有他的优势,但是相较于计算圆周率这种偏向逻辑计算方面,java这种多线程语言有明显的优势。

问题:线程崩溃会导致进程崩溃吗?

《计算机底层的秘密》作者 码农的荒岛求生解释说,答案是肯定了,我将以自己理解转述他的解答,可能会有误差,因为进程和进程之前是相互隔离的,而在一个进程里面,多个线程之间是紧密合作的,或者是互相透明的,换句话就是他们共同完成一个工作,他们之间的成果可能会互相印象,就好比一个造鞋子工厂,工厂就好比一个程序,进程就是造鞋这个过程,线程就是每个工人,每个工人之间是紧密合作的,甚至可能穿插工作,穿插工作的意思就是可能一个工序两个人合作,比如这里需要鞋子到了打包的环节,但是A工人(负责打包)发现鞋子依然有不干净的地方,又将鞋子返回给B工人(负责清洁的工人)进行清洁然后再进行打包,举例这些就是说明在一个进程里面多个线程之间是紧密合作,并且成果可能是互相影响的,所以当一个线程出现问题的时候,进程产生的结果就会偏离预期,这样就会被被操作系统不信任,这个时候操作系统手起刀落就把这个进程做掉了,这就是进程的崩溃,类比过来就是因为鞋子任何一个工序出了问题都没法生产出一个预期的产品,这个操作系统就相当于产品经理,这里做个假设,当C工人他是负责布料的,由于疏忽,他将A材质的皮革全部换成了B材质的,那么尽管后续的每步操作都完美符合预期,最终也无法生产出一个符合预期的产品,这很好理解,所以当一个线程出现崩溃了,那么这个进程就不会被操作系统所信任,更不会信任他的输出结果,这时候进程就会崩溃了。

PS:这里我听过一种说法,因为进程与进程之间是相互隔离的,就像我们平时用电脑,一般情况下,你QQ音乐软件崩溃了,你手动结束这个进程,或者等待进程都不会影响你干其他的,比如浏览网页什么的,但是线程之间是共享同一内存空间的,不同进程之间就像比如网易倒闭了,那我腾讯依旧笑嘻嘻,不会互相影响的,而线程就好比蓝洞,那蓝洞的策划全噶了,那么这个公司肯定就运营不起来了,但是我结合开发的经验,我在想如果对异常进行处理了,那么进程还会崩溃吗?在js中,比如我写了一段脚本程序,由于js是单线程的工作模式,那么我这个进程里面就只有一个线程,这就相当于我的公司只有一个员工,他负责所有环节,只要其他一个环节出问题,进程就无法继续下去了,但是在JavaScript中有try{}catch{}是可以将异常信息捕获,处理之后进程依旧可以继续执行,这里我个人感觉非常像作者jameswhale的一个解释情况,他说在java中,某个线程抛出异常没有捕获,对应的线程会崩溃,但是对应进程(JVM虚拟机)并不会随之崩溃,这样既有好处也有坏处,好处就是其他线程不受影响,坏处是如果没有外围监控很难察觉到线程是否崩溃。

基于这些我产生了一个新的疑问,如果对线程进行了抛出异常和捕获处理,那么这个线程算崩溃了嘛?其实按理来说,应该是也算是崩溃了,毕竟没有按照预期进行,但是做了捕获处理,处理比较好,比如之前那个例子,产品经理知道C工人最近失恋了,可能会出现失误他对这个人后面加了一道工序try{如果C工人选对了,继续下一步}catch{C工人选错了,D工人重新选择,审核通过},那么这种情况算做线程的崩溃嘛?我心中没有定论,我觉得说算也可以,因为try{这里的内容没有按照预期输出},但是由于catch{}的存在,进行了错误处理,相对于下一个线程或者下一道工序来说,C工人这里还是没出问题了,因为已经将异常数据处理成预期的了,这个我目前也没法解决,可能将来的学习中对进程和线程会有更深入了了解到时候就能解答自己的问题了。

参考文章:(作者有更加详情的图文解释,相对没有那么抽象)

线程与进程,你真得理解了吗_进程和线程_云深i不知处的博客-CSDN博客

猜你喜欢

转载自blog.csdn.net/weixin_54515240/article/details/129259109
今日推荐