并发与并行之我见(concurrency vs parallelism)
Contents
引子
近来把玩了Java 8 的一些特性,如Lambda 表达式、Stream,实在过瘾,有初学编程之快感,相见恨晚之情且按下不表。
其中 Stream 有一个parallelStream()
的API则着实勾起了我的好奇心,parallel(译过来是“并行”)这个词于我而言可谓陌生,在不算深入的使用和品味一番后,记以本文。本人才疏学浅,如有谬误之处,请不吝指教。
咬文嚼字
在 Android 的 Java 代码世界里并发(concurrency)这个词比较常见,而并行(parallelism)这个词则少之又少,且常常被人与前者混为一谈。实质上,这两个词是完全不同的概念。
援引Java官方的文档中定义(翻译可能不够准确,建议看原文):
parallelism 译为并行,指至少两个线程同一时间在运行。
concurrency 译为并发,指存在至少两个线程在执行着任务。更为一般性的并行,以时间分片作为执行单元的虚拟的并行。
我的理解:
首先得跟官方文档一样明确一个词义范围,否则就没有一点“可比性”了,提到这两个词多用其程序上执行“任务”层面的含义。
并行,就是字面意思,同一时刻执行多个任务。指执行程序代码的机器的物理上的一种能力,各个任务如同平行世界般的,形式上可以是多线程乃至多进程,被多个CPU同时运作。任务之间无任何依赖关系,不互斥、不交叉。
并发,指程序逻辑上的一种能力,支持多个任务同时存在一起被处理的能力。一个任务通常被划分为一个个的时间分片,比肩接踵般轮流的、可交替切换的被一个或多个CPU所执行,即不同任务的时间分片之间会有互斥、等待,一个任务可能因为CPU资源被抢走而被中断执行。
举个简单例子,单核CPU的机器,执行多线程化处理过的Java程序,一样称该程序支持并发,但它囿于机器性能永远做不到并行。
所提的并发和并行的概念都是为了最大化的利用多核CPU的能力,从而加速程序的执行。从这点来讲,那些将两个词混为一谈的人多半为一知半解的(看到这里的你已经不是了~)。
简单示例
parallel vs serial
parallel 并行的反义词是serial 串行。
以 Java 的 stream为例:
串行流计算总和
1 | int sum = widgets.stream() |
并行流计算总和
1 | int sumOfWeights = widgets.parallelStream() |
实质上,并行流与串行流的关键区别在于“分解”二字。
如图所示,将计算总和的任务,分解为一系列足够小的计算和任务(如只计算相邻的两个数的值),再将各个子任务执行结果合并到一起作为总结果输出,而且各个子任务可以同时被多个线程所执行。
ps. 并行流其实是基于Fork/Join框架实现的,本文就不细说了,对F/J有兴趣的可以看官方示例。
pps. “分解”其实就是“动态规划”。
以Android 的 AsyncTask 为例:
直接调用AsyncTask.execute()
其实为串行 (API >=11),多个AsyncTask存在于一个队列被一个接一个处理
使用指定线程池执行,AsyncTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR)
则为并行,多个AsyncTask可被指定线程池同时执行(取决于线程池的实现)。
Concurrent vs Sequential
Concurrent 并发(执行)的反义词是 Sequential 顺序(执行)
设有一系列任务:task1…taskN
顺序(执行):线程将task1开始执行到taskN执行结束,task1…taskN执行是连续的。
1 | Thread(){ |
并发(执行):将这系列任务提交给一组线程执行(一般为线程池),这组线程之间互相竞争CPU资源,task1…taskN 交替执行结束。
1 | threadPool = newFixedThreadPool(8); |
题外话
Android上的java代码写得多了,难免有一种与世界脱轨的感觉,java即将到9,而Android上大部分还只能用1.7的部分特性(API Level 24 才可以使用java 8的部分feature),“与时俱进”是程序猿必修课,希望我还能跟上这“日新月异”的世界。
另请参见
Package java.util.stream Description
Fork and Join: Java Can Excel at Painless Parallel Programming Too!
Java Fork and Join using ForkJoinPool
Concurrency vs Parallelism - What is the difference?