2017-01-18 你是怎么理解并发和并行的?
经常会被问道,并发和并行的区别是什么?
对于很多技术问题,每个人的理解都不相同。
今天我们讨论下,你是怎么理解并发、并行的。
👉并发、并行不是一个层面的概念
👉单核机器程序可以有并发,但是不能并行执行
👉一个正确的并发程序,应该可以在多核机器上正确的、高效的并行去执行
我是华卫。。。
我觉得, 并发应该是针对业务来讲, 指某一段时间内可以共同执行的计算任务; 并发应该是针对程序而言, 指某一刻时间点可以同时执行的程序代码;
一整个 :我觉得这个说的好,并发是单位时间的处理能力,无论是系统的还是CPU的,并行是一种处理方式
并发和并行都是同时执行多个任务,并发侧重在一个时间段,比如1分钟,1小时内接受多少个并发请求,并行则侧重于一个时间点多次请求同时发出;并发与并行都需要考虑的一个问题就是资源共享时,资源如何被获取、分配、释放或者说如何争抢资源的问题。
并行指同一时间段,并发指某一时刻。举例:十个售票窗口,但是只有5个售票员,每个售票员负责两个窗口,但是同一时刻只能操作一个窗口。那这个时候就是10并发,5并行。----转自群语录
💯 讨论到这里,其实并发并行的道理还是比较好理解的。
那么,问题在哪儿❓
:fist_right: 问题在于,怎样让我们编写的程序,能够在多核架构上并行的正确的执行。
这里就有很多概念了,锁,信号量,CAS,同步,阻塞, happens before等等。
罗列下同学们一些具有代表性的回答
同一时刻访问量大
不是同一个概念,并发是多个线程同时进行,并行是多个线程同时执行
并发和多线程 现在已经用了有一段时间了
tomcat本身不就是并发和多线程吗
并发,局限在一台机器,并行可以在多台机器
"并发 (concurrency)" 和 "并行 ( parallelism)" 是不同的。在单个 CPU 核上,线程通过时间片或者让出控制权来实现任务切换,达到 "同时" 运行多个任务的目的,这就是所谓的并发。但实际上任何时刻都只有一个任务被执行,其他任务通过某种算法来排队。多核 CPU 可以让同一进程内的 "多个线程" 做到真正意义上的同时运行,它们之间不需要排队 (依然会发生排队,因为线程数量可能超出 CPU 核数量,还有其他的进程等等。这里说的是一个理想状况),这才是并行。除了多核,并行计算还可能是多台机器上部署运行。
并发是一段时间内执行,并行是同一时间运行
并发和并行的区别就是一个人同时吃三个馒头和三个人同时吃三个馒头。
你吃饭吃到一半,电话来了,你一直到吃完了以后才去接,这就说明你不支持并发也不支持并行。 你吃饭吃到一半,电话来了,你停了下来接了电话,接完后继续吃饭,这说明你支持并发。 你吃饭吃到一半,电话来了,你一边打电话一边吃饭,这说明你支持并行。
那经常说的系统支持50的并发数是什么意思呢
即使是串行也有并发能力指标,并发和后台是否多线程多cpu这个无关,只看结果,不关心过程,结果就是单位时间响应了多少请求
我的理解是:并行指同一时间段,并发指某一时刻。举例:十个售票窗口,但是只有5个售票员,每个售票员负责两个窗口,但是同一时刻只能操作一个窗口。那这个时候就是10并行,5并发。
我的理解 并发:由外部请求发起,单位时间内大量请求。常说的并发数就是单位时间内请求的数量 并行:指应用内部处理任务的方式,以多线程为手段,多任务同时处理
简单说就是:并发是立体的,要多一些维度,时间,任务大小之类的。并行是平面的,说的是瞬时时间点上的处理能力。
并发 同一时间发生 并行 同一时间执行
抛砖引玉 --> 最后总结
科普-现代操作系统
当代操作系统都是分时系统。所谓分时,就是OS会把CPU的工作时间分成一个个很小的时间片。OS内核调度程序会把这些时间片分配给目前所有运行的线程。由于时间片都很短(在Linux上为5ms-800ms),所以我们看到好像自己程序好像一直在运行。
科普-SMP(Symmetric Multi-Processor)现代对称多处理架构的CPU

现代一个CPU都有多个核心,由于核心的运算速度远远大于内存的存取速度,所以在内存与CPU之间增加了多级缓存,用于平衡CPU和内存。
这也许是为什么编写并发程序难的罪魁祸首。:pray:
如果没有这几层缓存,程序执行的流程应该是这样。
内存读取数据 ==> 计算 ==> 写内存
有了缓存后的执行流程。
数据是否在缓存中 ==> 不存在 ==> 加载数据 ==> 计算 ==> 写内存
|| /\
||=======> 存在 =========>||
这就让原本读写的操作,增加了缓存判断、缓存失效、缓存同步等一些机制,导致我们并发程序没有正确编写就会出现各种数据可见性问题。
引申:MESI-缓存一致性协议
但是,试想下,如果没有CPU缓存机制,我们的程序可能会慢几个数量级。
说说并发
这里说的并发是指:concurrency
已经有很多小伙伴说了自己对并发的理解。
就我个人理解,所谓并发,一定是要有‘状态’。所谓状态,就是我们通常说的临界区。如果没有临界区,就谈不上所谓的并发。
可能理解起来有点抽象,我举个‘栗子‘ 😆。
public static int add(int a, int b) {
return a + b;
}
这段代码的调用,无论进程内多少个线程同时调用。在我看来,这个程序都不是一个并发的程序。
并发 != 多线程
我们有一个服务器程序,他有两个线程,一个线程做的是每隔5秒钟扫描本地磁盘,并打印目录下的所有文件名;另一个线程做的是,每隔5秒钟打印下当前时间戳。
你能说这个程序是并发程序么?多个线程的程序,并不意味着是一个并发程序。
来看一个并发的例子:
static final AtomicInteger a = new AtomicInteger(0);
public static int add(int b) {
return a.incrementAndGet() + b;
}
这段程序,如果多个线程调用,那么是一个并发的程序。因为所有线程都会有一个临界区(a),这是所有线程共享的。
所以说,并发是程序层的概念,跟cpu无关。
总之,多个线程回去访问一个临界区(有状态),那么程序就是并发程序。同时,我们就要关心如何处理这些临界区的并发问题了。关于怎么处理这里不深讨论。
聊聊并行
这里说的并行指的是:parellelism
还是看例子:
static volatile int a = 0;
public static int add(int b) {
return a+ b;
}
上面的例子,多线程去调用,就是一个并发的程序。
但是,如果在单核CPU下执行,他是没有问题的。第一,单核CPU读取自己的缓存,所以不会有缓存不一致问题。第二,单核CPU时间片分配给不同的线程,他们的执行时看到的数据都是同一份,计算结果也保存在同一块缓存中。
如果放到多核CPU下执行,假如我们希望a每一次递增的值,都只被计算一次。那么这个程序的执行结果就是不定的。
上面的程序经常被拿来当并发程序的经典教材,说会执行错误。但是这些教材都忘了一个前提条件,多核CPU下执行才会出错。
那么并行是什么?
并行就是具备多个CPU的情况下,OS内核可以把多个任务同时(可能相关、可能无关)分配给多个CPU执行。
如果这个程序是上面的例子,就会存在CPU1和CPU2同时访问上面例子中的a(假如=0)变量,将它从内存中load进缓存行(CPU都是以缓存行的形式加载内存中的数据的,一般为64 byte)。
之后,都传入参数b(假如=1),最后得到的结果都是1。
如果我们是希望a的每一次递增的值被计算一次,
那么这个并发程序在多CPU下并行执行的时候就会有问题。我们就需要使用锁,cas等进行并发控制。
并行跟程序无关,跟CPU架构相关。
java并发相关书籍推荐
并发:同一时间点2000个请求 并行:50个线程正在处理请求
并发请求,并行计算。
貌似我全还给老师了