并发/并行/同步/异步概念

Posted Andrew Study Notes

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了并发/并行/同步/异步概念相关的知识,希望对你有一定的参考价值。

1、应用程序和内核

内核具有最高权限,可以访问受保护的内存空间,可以访问底层的硬件设备。而这些是应用程序所不具备的,但应用程序可以通过调用内核提供的接口来间接访问或操作。所谓的常见的 IO 模型就是基于应用程序和内核之间的交互所提出来的。以一次网络 IO 请求过程中的 read 操作为例,请求数据会先拷贝到系统内核的缓冲区(内核空间),再从操作系统的内核缓冲区拷贝到应用程序的地址空间(用户空间)。而从内核空间将数据拷贝到用户空间过程中,就会经历两个阶段:

  • 等待数据准备
  • 拷贝数据

也正因为有了这两个阶段,才提出了各种网络 I/O 模型。

2、同步和异步

同步(Synchronised)和异步(Asynchronized)的概念描述的是应用程序与内核的交互方式。

  • 同步是指应用程序发起 I/O 请求后需要等待或者轮询内核 I/O 操作完成后才能继续执行。
  • 异步是指应用程序发起 I/O 请求后仍继续执行,当内核 I/O 操作完成后会通知应用程序,或者调用应用程序注册的回调函数。

3、阻塞和非阻塞

阻塞和非阻塞的概念描述的是应用程序调用内核 IO 操作的方式。

  • 阻塞是指 I/O 操作需要彻底完成后才返回到用户空间。
  • 非阻塞是指 I/O 操作被调用后立即返回给用户一个状态值,无需等到 I/O 操作彻底完成。

4、并发和并行

并发,在操作系统中,是指 一个时间段 中有几个程序都处于已启动运行到运行完毕之间,且这几个程序都是在同一个处理机上运行,但任一个时刻点上只有一个程序在处理机上运行。

  • 并发(concurrency):逻辑上具备同时处理多个任务的能力。
  • 并行(parallesim):物理上在同一时刻执行多个并发任务,依赖多核处理器等物理设备。

多线程或多进程是并行的基本条件,但单线程也可用协程做到并发。通常情况下,用多进程来实现分布式和负载平衡,减轻单进程垃圾回收压力;用多线程抢夺更多的处理器资源;用协程来提高处理器时间片利用率。现代系统中,多核 CPU 可以同时运行多个不同的进程或者线程。所以并发程序可以是并行的,也可以不是。

5、进程/线程/协程

进程(process)

  • 进程是资源分配的最小单位
  • 进程间不共享内存,每个进程拥有自己独立的内存
  • 进程间可以通过信号、信号量、共享内存、管道、队列等来通信
  • 新开进程开销大,并且 CPU 切换进程成本也大
  • 进程由操作系统调度
  • 多进程方式比多线程更加稳定

线程(thread)

  • 线程是程序执行流的最小单位
  • 线程是来自于进程的,一个进程下面可以开多个线程
  • 每个线程都有自己一个栈,不共享栈,但多个线程能共享同一个属于进程的堆
  • 线程因为是在同一个进程内的,可以共享内存
  • 线程也是由操作系统调度,线程是 CPU 调度的最小单位
  • 新开线程开销小于进程,CPU 在切换线程成本也小于进程
  • 某个线程发生致命错误会导致整个进程崩溃
  • 线程间读写变量存在锁的问题处理起来相对麻烦

协程(coroutine)

  • 对于操作系统来说只有进程和线程,协程的控制由应用程序显式调度,非抢占式的
  • 协程的执行最终靠的还是线程,应用程序来调度协程选择合适的线程来获取执行权
  • 切换非常快,成本低。一般占用栈大小远小于线程(协程 KB 级别,线程 MB 级别),所以可以开更多的协程
  • 协程比线程更轻量级

并行,并发,串行,同步,异步,阻塞,非阻塞,同步阻塞,同步非阻塞,异步阻塞,异步非阻塞

并行和并发

并发和并行从宏观上来讲都是同时处理多路请求的概念。但并发和并行又有区别,并行是指两个或者多个事件(多核线程)在同一时刻发生;而并发是指两个或多个事件(进程或者程序)在同一时间间隔内发生。计算机在宏观上并发,微观上并行。

 

    在操作系统中,并发是指一个时间段中有几个程序都处于已启动运行到运行完毕之间,且这几个程序都是在同一个处理机上运行,但任一个时刻点上只有一个程序在处理机上运行。

 

①程序与计算不再一一对应,一个程序副本可以有多个计算

②并发程序之间有相互制约关系,直接制约体现为一个程序需要另一个程序的计算结果,间接制约体现为多个程序竞争某一资源,如处理机、缓冲区等。

③并发程序在执行中是走走停停,断续推进的。

网上找到一个简单的例子:

你吃饭吃到一半,电话来了,你一直到吃完了以后才去接,这就说明你不支持并发也不支持并行。你吃饭吃到一半,电话来了,你停了下来接了电话,接完后继续吃饭,这说明你支持并发。你吃饭吃到一半,电话来了,你一边打电话一边吃饭,这说明你支持并行。并发的关键是你有处理多个任务的能力,不一定要同时。并行的关键是你有同时处理多个任务的能力。

(来自作者:龚昱阳 Dozer,链接:https://www.zhihu.com/question/33515481/answer/58849148

来源:知乎。著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。)

串行和并行:

指的是任务的执行方式。串行是指多个任务时,各个任务按顺序执行,完成一个之后才能进行下一个。并行指的是多个任务可以同时执行。异步是多个任务并行的前提条件。

同步和异步

指的是能否开启新的线程。同步不能开启新的线程,异步可以。个人理解同步是指两个线程的运行是相关的,其中一个线程要阻塞等待另外一个线程的运行。异步的意思是两个线程毫无相关,自己运行自己的。

在I/O流中它们是消息的通知机制。

所谓同步,就是在发出一个功能调用时,在没有得到结果之前,该调用就不返回。

 

异步的概念和同步相对。

当一个异步过程调用发出后,调用者不会立刻得到结果。

实际处理这个调用的部件是在调用发出后,

通过状态、通知来通知调用者,或通过回调函数处理这个调用。

 

举个例子(网上找的):

当到银行后,

.可以去ATM机前排队等候                       -- (排队等候)就是同步等待消息

 

 

.可以去大厅拿号,等到排到我的号时,

 柜台的人会通知我轮到我去办理业务.              -- (等待别人通知)就是异步等待消息.

在异步消息通知机制中,

等待消息者(在这个例子中就是等待办理业务的人)往往注册一个回调机制,在所等待的事件被触发时由触发机制(在这里是柜台的人)通过某种机制(在这里是写在小纸条上的号码)找到等待该事件的人.

在实际的程序中,

同步消息通知机制:就好比简单的read/write 操作,它们需要等待这两个操作成功才能返回;

                  同步, 是由处理消息者自己去等待消息是否被触发;

异步消息通知机制:类似于select/poll 之类的多路复用IO 操作,

                  当所关注的消息被触发时,由消息触发机制通知触发对消息的处理.

                  异步, 由触发机制来通知处理消息者;

阻塞和非阻塞:

阻塞/非阻塞, 它们是程序在等待消息(无所谓同步或者异步)时的状态.

阻塞

阻塞调用是指调用结果返回之前,当前线程会被挂起。函数只有在得到结果之后才会返回。

有人也许会把阻塞调用和同步调用等同起来,实际上他是不同的。

对于同步调用来说,很多时候当前线程还是激活的,只是从逻辑上当前函数没有返回而已。

非阻塞

非阻塞和阻塞的概念相对应,指在不能立刻得到结果之前,该函数不会阻塞当前线程,而会立刻返回。

继续上面的那个例子,

不论是排队等待,还是使用号码等待通知,

如果在这个等待的过程中,

. 等待者除了等待消息之外不能做其它的事情,那么该机制就是阻塞的,

  表现在程序中,也就是该程序一直阻塞在该函数调用处不能继续往下执行.

. 相反,有的人喜欢在银行办理这些业务的时候一边打打电话发发短信一边等待,这样的状态就是非阻塞的,

  因为他(等待者)没有阻塞在这个消息通知上,而是一边做自己的事情一边等待.

同步阻塞              同步非阻塞

异步阻塞              异步非阻塞

同步阻塞形式:

  效率是最低的,

  拿上面的例子来说,就是你专心排队,什么别的事都不做。

 

  实际程序中

  就是未对fd 设置O_NONBLOCK 标志位的read/write 操作,

异步阻塞形式:

  如果在银行等待办理业务的人采用的是异步的方式去等待消息被触发,也就是领了一张小纸条,

  假如在这段时间里他不能离开银行做其它的事情,那么很显然,这个人被阻塞在了这个等待的操作上面;

  异步操作是可以被阻塞住的,只不过它不是在处理消息时阻塞,而是在等待消息被触发时被阻塞.

  比如select 函数,

  假如传入的最后一个timeout 参数为NULL,那么如果所关注的事件没有一个被触发,

  程序就会一直阻塞在这个select 调用处.

 

同步非阻塞形式:

  实际上是效率低下的,

  想象一下你一边打着电话一边还需要抬头看到底队伍排到你了没有,

  如果把打电话和观察排队的位置看成是程序的两个操作的话,

  这个程序需要在这两种不同的行为之间来回的切换,效率可想而知是低下的;

 

  很多人会写阻塞的read/write 操作,

  但是别忘了可以对fd 设置O_NONBLOCK 标志位,这样就可以将同步操作变成非阻塞的了;

 

异步非阻塞形式:

  效率更高,

  因为打电话是你(等待者)的事情,而通知你则是柜台(消息触发机制)的事情,

  程序没有在两种不同的操作中来回切换.

  比如说,这个人突然发觉自己烟瘾犯了,需要出去抽根烟,

  于是他告诉大堂经理说,排到我这个号码的时候麻烦到外面通知我一下(注册一个回调函数),

  那么他就没有被阻塞在这个等待的操作上面,自然这个就是异步+非阻塞的方式了.

  如果使用异步非阻塞的情况,

  比如aio_*组的操作,当发起一个aio_read 操作时,函数会马上返回不会被阻塞,

  当所关注的事件被触发时会调用之前注册的回调函数进行处理,

以上是关于并发/并行/同步/异步概念的主要内容,如果未能解决你的问题,请参考以下文章

并发/并行/同步/异步概念

并发并行同步和异步

并行,并发,串行,同步,异步,阻塞,非阻塞,同步阻塞,同步非阻塞,异步阻塞,异步非阻塞

同步 ,异步,并发/并行,串行

数据挖掘_并行并发介绍和同步异步介绍

Java并发编程核心概念一览