百科问答小站 logo
百科问答小站 font logo



并发与并行的区别是什么? 第1页

  

user avatar   s.invalid 网友的相关建议: 
      

串行:喂?你在做什么呢?买菜啊?好的,到家了说一声。啊?到家了?那你到幼儿园接娃吧。

串行的特点:前一个任务没搞定,下一个任务就只能等着。


并行:来,这是你的盖浇饭,这是我的胡辣汤。咱俩一起吃。

并行的特点:两个任务在同一时刻互不干扰的同时执行。


并发:你去买个菜,顺路把邮件发了;路过幼儿园时带娃回家。

并发的特点:同时安排若干个任务,这些任务可以彼此穿插着进行;有些任务可能是并行的,比如买菜、发邮件和去幼儿园的某些路途是重叠的,这时你的确同时在做三件事;但进菜市场和发邮件和接娃三者是互斥的,每个时刻只能完成其中一件。换句话说,并发允许两个任务彼此干扰。



要点:串行还是并发,这都是任务安排者视角看到的东西。前者要求你看到前一个任务结束了,下一个任务才能安排;而后者呢,你可以同时提交许多任务,执行者(们)之间会相互协调并自己安排执行顺序(但未必合理,比如可能出现死锁)——总之,你把任务安排下去就不用管了。

相比之下,“并行”是任务执行者视角的东西,和前两者所处平面不同。


典型案例:你买了个新硬盘,打算把自己的重要文件复制过去。于是你找到music目录,把所有的音乐文件夹选中,复制50G音乐到新硬盘;然后打开photo目录,把100G照片复制到新硬盘;又打开mov目录,把800G视频复制到新硬盘……

最后,你看到Windows显示了10个文件复制窗口;其中一个窗口的提示是“还有一千六百个文件待复制,需要三天零八小时七分钟三十二秒”。


这就是典型的“并发”任务。

在这个场景里,你同时启动了10个文件复制进程,帮你复制十大类文件。

如果没有“并发”支持,你只能先复制一个文件夹,等上半小时,看它复制完了才能继续复制下一个。这当然很累人。

一旦有了并发支持,你就能同时启动十个复制任务。在计算机忙碌的同时,你完全可以出去旅个游……


但是,细心的你可能会注意到:如果这十个文件复制任务没有分成十个进程去做,而是写个批处理甚至干脆用Linux的dd命令全盘复制,那么复制完所有文件只需五六个小时。

这是因为,十个进程会彼此争抢资源;而每次进程执行权切换,硬盘就不得不重新寻道——这是非常非常浪费时间的。

其结果,就是把本来五六个小时就能搞定的事情,争抢成了三天都搞不定……


换句话说,这里面没有并行,只有并发。

说的更清晰点,对电脑操作者,你的确是“并发”了十个任务;但对程序这个执行者来说,它们仍然是“串行”使用硬盘——进程1用200ms,交出控制权;换进程2用200ms硬盘,交出控制权;然后是进程3、4、5、6、7……

它们只是快速切换执行权、从而让你得到了一个“同时执行”的假象而已。


因此,对这类任务……其实你还是自己写个批处理更好。节省你的生命,也节省硬盘的使用寿命。


当然,如果你的两台电脑分别装了块新硬盘,显然它们对各自硬盘读写就是“并行”的。互不干扰嘛。

你完全可以用第三台电脑远程登陆上去,然后分别在两者上面启动各自的复制进程——只要没有数据相关,先让电脑A复制完再去捣鼓电脑B,这显然是不智的。


类似的,同一台电脑里面,网卡收发信息和硬盘读写并不相关;CPU忙碌时让显卡空闲也是极大的浪费——换句话说,不同任务有不同的执行实体;那么我们当然不应该“在CPU上执行任务A”时“禁止任务B使用网卡”。

没错,只要执行任务的硬件不同(包括但不限于不同的CPU核心、网卡A和网卡B、C、D、显卡、硬盘、打印机等等等等),它们就可以并行工作。


一个好的程序,一方面不应该在单个硬件上造成过多切换(比如在一块硬盘上同时开10个文件复制进程就是一种极其低效的使用方式),另一方面则要尽量利用每个空闲的硬件(比如任务A使用硬盘时应该允许任务B使用网卡),这才不至于降低执行效率、使得硬件使用不够充分。


尤其是,纠正一个错误的观念:并不像一般人以为的“单核单线程没有并行”;事实上,哪怕用了单核单线程CPU的电脑,它上面也存在真正的“并行”。

只不过,这个并行并不是CPU内部的、线程之间的并行;而是CPU执行程序的同时,DMA控制器也在执行着网络报文收发、磁盘读写、音视频播放/录制等等任务。


综上,串行在执行单个简单任务时,执行速率是最高的。因为完全没有干扰,任何硬件想用就用。


但是,串行方式的硬件利用率不高。比如当某个任务不需要使用打印机时,在它完成之前,打印机就只能闲置。


为了解决这个问题,我们首先要允许“并发”。

“并发”的意思是,你可以同时提交多个任务,但系统并不能保证它们可以并行执行。

甚至于,在极端的、类似“单个硬盘上同时启动10个复制进程”的场景里,“并发”反而引起了过多的切换动作,成几倍甚至几十倍的降低了文件复制效率——这种场景下,并发甚至要不如串行。


想要提高并发的效率,我们就必须深入进去,关注“这些任务之间究竟有没有出现并行”。


比如,如果文件复制程序写的非常糙,那么很可能是“先从旧硬盘读取数据,然后写入新硬盘;数据写入新硬盘后,继续从旧硬盘读取数据”……

这在单硬盘上是合理的,少了一些寻道操作;但在两块硬盘的场景下,这就相当于“串行使用两块硬盘”——这个利用效率显然太低了,每块硬盘只有50%左右的利用率(当然,现代OS会主动多读一些数据到磁盘缓存,这个机制可以有效提高硬盘利用率)。

那么,如果同时启动两个复制进程,反而会不时出现“进程A读旧硬盘,同时进程B写新硬盘”这种场景,从而把每块硬盘的利用率提高到60%~80%。


换句话说,“并发”的确经常能让“并行”自然而然的出现,硬盘利用率也的确被提高了;只是这种提高缺乏保证(比如,运气不好时,复制进程A可能和进程B争着读取旧硬盘,从而导致很多不必要的寻道动作);而且,由于并发并不保证合理的执行顺序,反而经常“搬起石头砸自己的脚”。

比如,一旦同时启动更多复制进程(比如三五个),那么过多的进程切换引起的过多的磁盘重新寻道动作就会抵消一切好处。


因此,很多时候,我们需要一个优秀的、头脑清醒的程序员;只有在他的有意识的安排下,才能在确保硬件利用率的同时、不因过多的争抢和切换降低执行效率。




  

相关话题

  编译器是如何编译自己的? 
  常说「Java 在虚拟机中运行」,请问这个虚拟机可以视为 Java 语言的解释器吗? 
  面向对象中接口应该更抽象还是更具象? 
  服务端把客户端几次发的数据一起接受了,是怎么回事?socket,Tcp协议 
  服务端把客户端几次发的数据一起接受了,是怎么回事?socket,Tcp协议 
  go mutex阻塞线程吗,如果不阻塞,为什么呢? 
  大括号不换行的坏处有什么?为什么有人不换行? 
  Java为什么设计成`String`不能用`==`比较值? 
  Java的语法规则是怎么传播开来的?(如若回答,请看完补充说明)? 
  常说「Java 在虚拟机中运行」,请问这个虚拟机可以视为 Java 语言的解释器吗? 

前一个讨论
299入手了飞利浦9500,大湿说要耳放才能发挥真实实力,低频缺这么多,真的靠标准的耳放就能解决吗?
下一个讨论
环境音与主动降噪有什么区别?





© 2024-09-19 - tinynew.org. All Rights Reserved.
© 2024-09-19 - tinynew.org. 保留所有权利