前言:
阅读本文章你将大概的理清 同步 异步 阻塞 非阻塞 并发 并行 高并发 多线程 进程 线程的概念,和它们之间的关系,阅读了大量文章后的自我总结分享不喜勿喷,
1.并发与并行的区别是什么?
顾名思义,「并发」强调的是可以一起「出『发』」,「并行」强调的是可以一起「执『行』」。
并行”概念是“并发”概念的一个子集。
举例:
你吃饭吃到一半,电话来了,你一直到吃完了以后才去接,这就说明你不支持并发也不支持并行。
你吃饭吃到一半,电话来了,你停了下来接了电话,接完后继续吃饭,这说明你支持并发。
你吃饭吃到一半,电话来了,你一边打电话一边吃饭,这说明你支持并行。
并发的关键是你有处理多个任务的能力,不一定要同时。
并行的关键是你有同时处理多个任务的能力。
所以我认为它们最关键的点就是:是否是『同时』。
如果某个系统支持两个或者多个动作(Action)同时存在,那么这个系统就是一个并发系统。如果某个系统支持两个或者多个动作同时执行,那么这个系统就是一个并行系统。
并发和并行其实是异步线程实现的两种形式。并行其实是真正的异步,多核CUP可以同时开启多条线程供多个任务同时执行,互不干扰,但是并发就不一样了,是一个伪异步。在单核CUP中只能有一条线程,但是又想执行多个任务。这个时候,只能在一条线程上不停的切换任务,比如任务A执行了20%,任务A停下里,线程让给任务B,任务执行了30%停下,再让任务A执行。这样我们用的时候,由于CUP处理速度快,你看起来好像是同时执行,其实不是的,同一时间只会执行单个任务。
串行是同步线程的实现方式。就是任务A执行结束才能开始执行B,单个线程只能执行一个任务,就如单行道只能行驶一辆车。
2.线程与进程
进程:指一个内存中运行的应用程序,一个应用程序可以同时运行多个进程。
线程:进程内部的一个独立执行单元,一个进程可以同时并发的运行多个线程。
进程就相当于是火车;
线程就相当于是车厢 。
线程在进程下行进(车厢无法运行,它需要依赖火车)
一个进程可以包含多个线程(一辆火车可以有多个车厢)
线程消耗的资源比进程小的多(多个车厢比多列火车消耗资源少的多)
中央处理器cpu:对计算的硬件资源(计算核心.缓存)的封装
一个计算核心在物理逻辑上只有一个线程:单核单线程
我们每次都是调用cpu的一个计算核心去处理一个线程任务,cpu的单个核心的计算资源还有很大的剩余
于是我们通过某种技术将一个核心的计算能力封装成两个线程,同时计算处理两个任务,
3.同步 阻塞 异步 非阻塞
同步:同步是指一个进程在执行到某个接口的时候,若该请求需要一段时间才能返回信息,那么这个进程将会一直等待下去,直到收到返回信息才继续执行下去,同步往往伴随着阻塞
异步:异步是指进程不需要一直等下去,而是继续执行下面的操作,不管其他进程的状态。当有消息返回时系统会通知进程进行处理,这样可以提高执行的效率。异步是非阻塞的
同步和异步的区别:是否开启新线程
阻塞和非阻塞的区别:当前线程是否挂起,即是否释放cpu
事实上,所谓的同步就是指阻塞式操作,而异步就是非阻塞式操作。
public static void main(string[] args){
doSomething1();
doSomething2();
}
//main方法是程序入口,主函数,在主线程上运行
同步/异步 概念的理解:
关于同步,我们知道jvm解释执行class文件时候,就是按照代码从上到下的顺序执行的,符合编码逻辑,如果一个main方法中调用了doSomething1,doSomething2两个接口,正常情况下doSomething2开始的前提是doSomething1执行结束,相当于代码执行就是一条总线下来的,doSomething1出现异常,那就不会轮到doSomething2执行了。doSomething2的执行又依赖于doSomething1的执行结果,所以同步用于操作具有依赖关系,保证数据一致性的情况
例如正在写的数据以后可能被另一个线程读到,或者正在读的数据可能已经被另一个线程写过了,那么这些数据就必须进行同步存取(数据库操作中的排他锁就是最好的例子)。
在多线程情况下,为了实现同步的目的,我们可以将涉及到共享数据的操作进行加锁
关于异步,有时候当doSomething1耗时很大,而doSomething2的执行又不依赖于doSomething1的执行结果,比如我们现在有这么个需求,申通会在每天定时把快件的物流信息推送给我们电商平台,当他们调用我们接口推送时候,我们做了两个操作,一个是把物流信息写入db,一个是给用户发消息告知快件当前状态,这两个操作其实是没有强关联性的,我们希望的是申通推送消息的时候我们立即让用户知道,而不是说我们存db出错了,同时影响到了通知用户这个操作。所以程序正确执行逻辑应该是,推送信息过来,我存db的同时也给客户发了消息。所以异步适用于调用的接口操作和接口后的代码没有依赖关系,为了提示响应速度的情况
在多线程的情况下,为了实现异步的目的,我们可以在主线程执行到doSomethong1时开启一个新的线程去执行,而主线程继续执行其后的操作
总而言之:同步和异步是在不同业务场景需要实现的目的,
而同步加锁(串行)和异步开启新线程(并发,并行)都是实现目的的方式
而同步异步都依赖多线程环境,否则在单线程情况下同步加锁毫无意义,异步开启新线程也只是并发,实际还是只有一条线程,是伪异步.
同步/异步是针对谁而言:
一个方法内又调用了其他的方法的方法的执行过程
4.高并发 多线程
高并发是指在同一个时间点,有很多用户同时的访问同一 API 接口或者 Url 地址的一种程序运行过程中会出现的情况,如果这些接口设计到对共享数据(如数据库中的同一数据增删改查)的操作,就可能出现如超卖,库存剩余等问题,当然前提是服务器端采用多线程机制来处理这些请求,如果是服务器端是采用单线程处理,同一时间的请求也将入队后一个一个处理也就不存在上述问题.
5.总结
高并发-服务器端多线程同时处理-虽然多线程处理能够提高处理请求的速度,但是也会带来各种问题,
为了享受多线程同时处理的高效率和解决其所带来的问题,我们将请求接口的操作进行规类,
如果是操作是需要同步的,涉及到共享数据的操作,我们可以同步加锁(串行)来解决—高效+数据一致性
会带来各种问题,
为了享受多线程同时处理的高效率和解决其所带来的问题,我们将请求接口的操作进行规类,
如果是操作是需要同步的,涉及到共享数据的操作,我们可以同步加锁(串行)来解决—高效+数据一致性
如果操作支持异步,我们可以开启新线程(并发,并行)来处理—高效+高效