美文网首页
进程与线程,并发与并行

进程与线程,并发与并行

作者: 程序员汪汪 | 来源:发表于2021-04-13 18:41 被阅读0次

在进行Java多线程内容之前,需要简单先了解一下程序、进程、线程、并行与并发这些概念,弄懂了这个,对于学习多线程,或者说对你理解多线程可能会有一定的帮助。

程序、进程以及线程

程序

程序是为了完成特定任务,用某种语言编写的一组指令的集合。例如:QQ、迅雷、Chrome。

进程

程序的一次执行过程,或是正在运行的一个程序。是一个动态的过程,它有自身的产生、存在和消亡的过程——生命周期。例如:正在运行的QQ、迅雷、Chrome。

程序是静态的,进程是动态的,进程作为资源分配的基本单位,系统会在运行时为每个进程分配不同的内存区域。进程切换的开销大。

线程

进程可进一步细化为线程,是一个程序内部的一条执行路径。若一个进程同一时间并行执行多个线程,就是支持多线程的。线程作为调度和执行的单位,每个线程拥有独立的运行栈和程序计数器,线程切换的开销小。

一个进程中的多个线程共享相同的内存单元(或者说内存地址空间),它们从同一堆中分配对象,可以访问相同的变量和对象,这就使得线程间通信更简便、高效,但多个线程操作共享的系统资源可能就会带来安全隐患。

并发与并行

并发

并发(Concurrency)是一个比较抽象的概念。

假设你现在要铺一条长1000米宽50米的路,你制定了一个方案,第一步干什么,第二部干什么等等,你一个人按照这个制定的方案来铺路,并且一个人从头干到尾,那么这个过程就是一个”串行“的过程。根据进程一词的本意:事物发展变化或进行的过程。那么你按照这个方案上的思路步骤来铺路的过程,就可以称之为”进程“(这里的进程指的是这个词的本意)。

有人可能会问,这个描述方案执行过程的进程,和上面说的计算机中的进程有什么不一样?其实本质上是没有区别的。先说程序,本意是:事情进行的步骤、次序。如果我们把方案(铺路的步骤、次序)用纸和笔写下来,就得到了一个程序,软件开发也是如此,只不过用的不是纸和笔,而是计算机和某种编程语言。

现在按照方案一步一步执行,实际动手去进行铺路工作,那么这个过程就是进程。如果你把这个铺路的方案用某种编程语言实现了,放在计算机里运行起来,那么计算机里就有铺路程序的进程。一个是实际工作的过程,一个是在计算机里模拟实际工作的过程,本质上都是一样的。

现在你觉得这个方案不行,一个人干太慢了,你想要再找1个人或者10个、20个人一起干,这个时候就要考虑如何分工的问题,你就需要把这个铺路的工作按照路的长度、宽度或铺路的步骤等各种方式进行拆分,拆分后再各自开工。不管怎么拆,只要最终能铺好这条路,都意味着你得到了并发的进程。换句话说就是,你有一个方案,可以让多个人把事情做的更高效。注意是可以,而不是“必然”让事情更高效。是否高效要看到底是怎么执行的,这个稍后再讲。

举个例子:如果你要下载一个很大的资源(视频、软件等),直接下载这个文件,会很慢,需要很长的时间,一个并发的做法就是把这个文件分成几段,然后各自启动下载,全部下载完成后再按照顺序进行拼接。这样的程序写出来就是一个并发的程序,如果这个程序运行起来就是并发的进程。

这个时候就会出现一个问题,当你想实现这个并发的程序时,你该怎么告诉操作系统你的程序中的一些步骤是并发的?更确切的说,你要怎么表达如下两个问题:

  • 几个任务是并发的?
  • 并发的任务之间是怎么协作的?

为了解决这两个问题,人们总结了一些方法,并称其为“并发模型”,比如:Fork&Join模型、Actor模型、线程&锁模型等等。

以Java为例,大家想表达并发就启动新的线程(Thread)或者使用线程池;想要线程之间进行交互,就要共享数据,但是并发的线程如果同时修改一份数据,就有可能出错,为了解决这个问题就引入了锁(Lock)或者使用其他同步工具。

并行

现在我们有了并发的想法,然后进入执行层面。

回到上面的铺路的例子,如果你把这个铺路方案改成了一个20个人可以一起干活的方案,但是实际上,由于你给的工资过低,只招到了1个人,那这个方案能不能用?当然能用,让他先干第1个人的活,再干第2个人的活......

你一看只雇佣一个人,进度太慢了,提高了工资,现在你雇佣了10个人,就可以让第1个人干第1人份和第2人份的活,再让第2个人干第3和第4人分的活......而这10个人同时在施工现场上干活,就是并行(Parallelism)。

在计算机中,程序能否并行运行,要看物理上有多少个CPU核心可以同时干活,或者有多少台可用的物理主机。

比如你写了个Java程序,同时启动了4个线程,但CPU只有单核,那么同一时刻只有一个线程在运行。如果有4个CPU核心,那么可以做到4个线程完全并行运行。如果只有2个核心,那么同一时刻,最多只有两个线程在并行运行。

为什么要并发

把事情设计成并发有什么好处?这个得分情况讨论,假如能同时干活的只有1个人,其实没有什么好处,此时并发的方法总耗时>=串行的方法耗时,因为并发或多或少会引入沟通和协作的成本,最小的代价就是不需要沟通,此时并发的方法和串行的方法工作耗时是一样的。

但是并发的巨大优势是在可以同时干活的人数变多时,能得到并行的好处。还是上面铺路的例子,如果我们设计的是可以20个人同时工作的方案,并且配上了20个工人,那么这个时候,干活的效率可就远远大于1个人干活的情况了。回到计算机上,假如现在有一个并发的程序,它在只有1个核心的CPU的机器上跑,在4核CPU上也可以跑,那么核心数越多,程序执行完的速度就越快,而不管在哪里跑,程序本身不用做变化,这能够极大的节约开发成本。

并发和并行的关系

并发和并行说的就不是一件事,并发(Concurrency)在计算机领域中,应该理解为一种处理问题的方法,而并行(parallelism)说的则是执行的方法。

如果想让一个事情变得容易并行,我们得先制定一个并发的方法,如果事情压根就没有并发的方法,或者说不适合使用并发的方法,那么,有多少个可以干活的人也不能并行。比你不让20个人去铺路,而是去拧同一个灯泡,也只有一个人踩在梯子上去拧,其他19个人只能干看着, 如果你强行让其他人参与,每人拧一小下,也不是不行,那效率肯定没有一个人拧灯泡快,因为上下梯子也是需要时间的。

对于一个问题,能不能找到并发的方法,取决于问题本身,有些问题很容易并发,有些问题可以部分并发其余的串行,有些问题本身就不能并发,或者说并发只会大大降低执行的效率。找不到并发的方法也就意味着,不管CPU有多少个核心,也不能并行。

在硬件条件确定的情况下,并行的上限应该取决于并发方法的设计。比如,我现在有一个4核CPU,而你的程序只能跑满2个核心,那么多出来的2个核心就是浪费的,如果你的程序能跑满4个核心,那么这个时候,执行的效率应该是最高的。

那么 ,是不是拥有单核CPU的计算机,就不存在并行?也不是的,比如显卡、网卡、磁盘这些组件是可以并行运行的。

常见的误解

对于并发和并行,你可能看过下面的解释:

并发是多个任务交替使用CPU,同一时刻只有一个任务在跑;并行是多个任务同时跑

这个理解不能说全错,但是合到一起就很容易让人误解。这个误解就是:并行和并发是非此即彼的概念,一个状态,要么就是并行,要么就是并发。这是个错误的理解,实际上并发描述的是如何处理,而并行描述的是如何执行

对于:

并发是多个任务交替使用CPU,同一时刻只有一个任务在跑;

正确的理解:针对一个问题,想到了一个可以将它拆解为多个并发任务的方法,这些任务在执行时,由于只有一个CPU核心工作,所以只能切换交替着跑。

对于:

并行是多个任务同时跑

正确理解:这些并行执行的任务,是为了解决同一个问题的,那么这些任务之间,它们既是并发的,也是并行的。

那么可不可以只并行,不并发?可以,但是这就意味着并行的程序之间没有什么关联,各干各的,就像大街上来来往往的陌生人一样,他们的确是并行的。但是一群不认识的人,各干各的是不能一起解决问题的,要一起就得有同一个目标,制定一套沟通的方法,形成并发的方案,这种形式在现实当中就是公司。

为什么要这么理解并发

将大的任务拆解为许多可以并发的小任务是重要的编程思想

并行和并发的总结

并发(Concurrency)在计算机领域中,应该理解为一种处理或解决问题的方法,而并行(parallelism)说的则是执行的方法。

并发:将一个大的任务,拆分为多个可以同时执行的小任务。

执行:这些拆分后的得到的小任务跑在了单核CPU上,只能交替着执行;跑在多核CPU上,多个CPU核心同时工作,就是并行执行。

单核CPU不能真正的并行执行程序,只是CPU的执行速度很快,给每个线程的CPU时间片又非常短,然后CPU在各个线程间来回切换着执行,所以给用户的感觉就是多个线程同时执行的。

相关文章

网友评论

      本文标题:进程与线程,并发与并行

      本文链接:https://www.haomeiwen.com/subject/gevclltx.html