一、理解同步、异步、阻塞、非阻塞

  出场人物:老张,水壶两把(普通水壶,简称水壶;会响的水壶,简称响水壶)。
  1 老张把水壶放到火上,立等水开。(同步阻塞)
    老张觉得自己有点傻。
  2 老张把水壶放到火上,去客厅看电视,时不时去厨房看看水开没有。(同步非阻塞)
    老张还是觉得自己有点傻,于是变高端了,买了把会响笛的那种水壶。水开之后,能大声发出嘀~~~~的噪音。
  3 老张把响水壶放到火上,立等水开。(异步阻塞)
    老张觉得这样傻等意义不大。
  4 老张把响水壶放到火上,去客厅看电视,水壶响之前不再去看它了,响了再去拿壶。(异步非阻塞)
    老张觉得自己聪明了。

  所谓同步异步,只是对于水壶而言。
  普通水壶,同步;响水壶,异步。
  虽然都能干活,但响水壶可以在自己完工之后,提示老张水开了。这是普通水壶所不能及的。
  同步只能让调用者去轮询自己(情况2中),造成老张效率的低下。

  所谓阻塞非阻塞,仅仅对于老张而言。
  立等的老张,阻塞;看电视的老张,非阻塞。

  情况1和情况3中老张就是阻塞的,媳妇喊他都不知道。虽然3中响水壶是异步的,可对于立等的老张没有太大的意义。所以一般异步是配合非阻塞使用的,这样才能发挥异步的效用。

  再找一个买书的例子:
  异步/同步:
    异步: 你去书店,问《如何征服美少女》到货没,老板说,没到货,到货了给你打电话。你就走了,而且不需要再没接到老板电话之前再跑到书店问。
    同步:你去书店,问《如何征服美少女》到货没,老板说,没到货,你走了,过了一段时间,你又到书店,问《如何征服美少女》到货没,老板说没有,。。。。就这样,你不断的来书店自己询问。直到你鞋都跑破了.....
    注意:你离开书店(不管是异步还是同步),是可以干自己的事情的,比如去做个大保健。

  阻塞/非阻塞
    阻塞:你去书店,问《如何征服美少女》到货没有,老板说,没到货,于是你就在书店苦等,等书到货,除了干坐着,啥也干不了,直到书来。
    非阻塞:你去书店,问《如何征服美少女》到货没,老板说,没到货,你就走了。(至于还来不来书店,取决于你的心情吧。但是在计算机中,没处理完的事情,是要处理的。)

  异步/同步 是你的到消息的方式,关注的是消息通信机制 (synchronous communication/ asynchronous communication)
  阻塞/非阻塞是你怎样处理事情,关注的是程序在等待调用结果(消息,返回值)时的状态
  两组概念不是一个层面上的。

在上面的例子中,你就相当于计算机中的 进程 ,你的两条腿就相当于CPU。(比喻很牵强也)

二、解析
  在高性能的I/O设计中,有两个比较著名的模式Reactor和Proactor模式,其中Reactor模式用于同步I/O,而Proactor运用于异步I/O操作。

  在比较这两个模式之前,我们首先的搞明白几个概念,什么是阻塞和非阻塞,什么是同步和异步。

  同步和异步是针对应用程序和内核的交互而言的,同步指的是用户进程触发IO操作并等待或者轮询的去查看IO操作是否就绪,而异步是指用户进程触发IO操作以后便开始做自己的事情,而当IO操作已经完成的时候会得到IO完成的通知(异步的特点就是通知)。

  而阻塞和非阻塞是针对于进程在访问数据的时候,根据IO操作的就绪状态来采取的不同方式,说白了是一种读取或者写入操作函数的实现方式,阻塞方式下读取或者写入函数将一直等待,而非阻塞方式下,读取或者写入函数会立即返回一个状态值。

  首先一个IO操作其实分成了两个步骤:发起IO请求和实际的IO操作。

  同步IO和异步IO的区别就在于第二个步骤是否阻塞,如果实际的IO读写阻塞请求进程,那么就是同步IO,因此阻塞IO、非阻塞IO、IO服用、信号驱动IO都是同步IO,如果不阻塞,而是操作系统帮你做完IO操作再将结果返回给你,那么就是异步IO。

  阻塞IO和非阻塞IO的区别在于第一步,发起IO请求是否会被阻塞,如果阻塞直到完成那么就是传统的阻塞IO,如果不阻塞,那么就是非阻塞IO。

  说到阻塞,首先得说说I/O等待。I/O等待是不可避免的,那么既然有了等待,就会有阻塞,但是注意,我们说的阻塞是指当前发起I/O操作的进程被阻塞
  同步阻塞I/O便是指,当进程调用某些涉及I/O操作的系统调用或库函数时,比如accept()(注意accept也算在了i/o操作)、send()、recv()等,进程便暂停下来,等待I/O操作完成再继续运行。这是一种简单而有效的I/O模型,它可以和多进程结合起来有效的利用CPU资源,但是代价就是多进程的大量内存开销。

  同步阻塞 进程坐水,就不能烧粥
  同步非阻塞  类似于用一个进程坐水,烧粥. while(true){if... if... }  好处就是一个进程处理多个i/o请求. 劣势就是需要不停的轮询.

  区别在于等不等待数据就绪. 因为数据占了等待的80%时间. 同步非阻塞的优势就是一个进程里同时处理多个I/O操作。

  在同步阻塞I/O中,进程实际上等待的时间可能包括两部分,一个是等待数据的就绪,另一个是等待数据的复制,对于网络I/O来说,前者的时间可能要更长一些。与此不同的是,同步非阻塞I/O的调用不会等待数据的就绪,如果数据不可读或者不可写,它会立即返回告诉进程。

  比如我们使用非阻塞recv()接收网络数据的时候,如果网卡缓冲区中没有可接收的数据,函数就及时返回,告诉进程没有数据可读了。相比于阻塞I/O,这种非阻塞I/O结合反复的轮询来尝试
数据是否就绪,防止进程被阻塞,最大的好处便在于可以在一个进程里同时处理多个I/O操作。但正是由于需要进程执行多次的轮询来查看数据是否就绪,这花费了大量的CPU时间,使得进程处于忙碌等待状态。

  非阻塞I/O一般只针对网络I/O有效,我们只要在socket的选项设置中使用O_NONBLOCK即可,这样对于该socket的send()或recv()便采用非阻塞方式。
  如果服务器想要同时接收多个TCP连接的数据,就必须轮流对每个socket调用接收数据的方法,比如recv()。不管这些socket有没有可以接收的数据,都要询问一遍,假如大部分socket并没有数据可以接收,那么进程便会浪费很多CPU时间用于检查这些socket,这显然不是我们所希望看到的。

  同步和异步,阻塞和非阻塞,有些混用,其实它们完全不是一回事,而且它们修饰的对象也不相同。
  阻塞和非阻塞是指当进程访问的数据如果尚未就绪,进程是否需要等待,简单说这相当于函数内部的实现区别,也就是未就绪时是直接返回还是等待就绪;

  而同步和异步是指访问数据的机制,同步一般指主动请求并等待I/O操作完毕的方式,当数据就绪后在读写的时候必须阻塞(区别就绪与读写二个阶段,同步的读写必须阻塞),异步则指主动请求数据后便可以继续处理其它任务,随后等待I/O,操作完毕的通知,这可以使进程在数据读写时也不阻塞。(等待"通知")

  多数情况下,Web服务器对这些请求采用基于队列的自由竞争,通过多执行流(多进程或多线程)来充分占 用CPU以及I/O资源,减少任何无辜的等待时间,这其中包括了很多种具体实现的并发策略,在实际应用中,特别是Web服务器,同时处理大量的文件描述符是必不可少的.多路I/O就绪通知的出现,提供了对大量文件描述符就绪检查的高性能方案,它允许进程(比如电子屏,会闻到各个饭馆做好饭菜的味道)通过一种方法来同时监视所有文件描述符,并可以快速获得所有就绪的文件描述符,然后只针对这些文件描述符进行数据访问。
  回到买面条的故事中,假如你不止买了一份面条,还在其它几个小吃店买了饺子、粥、馅饼等,因为一起逛街的朋友看到你的面条后也饿了。这些东西都需要时间来等待制作。在同步非阻塞I/O模型中,你要轮流不停的去各个小吃店询问进度,痛苦不堪。现在引入多路I/O就绪通知后,小吃城管理处给大厅安装了一块电子屏幕,以后所有小吃店的食物做好后,都会显示在屏幕上,这可真是个好消息,你只需要间隔性的看看大屏幕就可以了,也许你还可以同时逛逛附近的商店,在不远处也可以看到大屏幕。

  多路就绪:1.强调多路. 2.只针对请求数据是否就绪.不针对i/o读写
  epoll针对的是这样的场景.

  select, epoll都只需要进程(我)被动接收到数据就绪(面条)"通知".符合异步的定义. 不需要一直在饭馆等(同步阻塞).或轮询(同步非阻塞).

Linux-同步异步非阻塞阻塞的解析的更多相关文章

  1. 同步异步IO,阻塞非阻塞

    同步异步 同步IO操作:导致请求进程阻塞,知道IO操作完成. 异步IO操作:不导致进程阻塞. 在处理(网络) IO 的时候,阻塞和非阻塞都是同步IO, 阻塞,就是调用我(函数),我(函数)没有接收完数 ...

  2. C# 【一】进程 , 线程 , 微线程 , 同步 , 异步 , 并发 , 并行 , 阻塞 , 非阻塞

    一 理解篇 前言 本文仅仅用作借鉴使用,作者刚入行不久,所以请不小心看到这篇文章的朋友,手下留情. 本文以小故事的形式进行叙述,逻辑不通之处.请理解. 如有错误 ,欢迎指出. 谢谢.          ...

  3. GCD同步异步 串行并行大解析

    /** 核心概念 任务:block里需要执行的操作 队列:把任务添加进入队列中,按照先进先出的原则来执行任务  串行队列:一个一个的执行 并行队列:可以让多个任务并发(同时)执行(自动开启多个线程同时 ...

  4. {Python之进程} 背景知识 什么是进程 进程调度 并发与并行 同步\异步\阻塞\非阻塞 进程的创建与结束 multiprocess模块 进程池和mutiprocess.Poll

    Python之进程 进程 本节目录 一 背景知识 二 什么是进程 三 进程调度 四 并发与并行 五 同步\异步\阻塞\非阻塞 六 进程的创建与结束 七 multiprocess模块 八 进程池和mut ...

  5. 理解同步,异步,阻塞,非阻塞,多路复用,事件驱动IO

    以下是IO的一个基本过程 先理解一下用户空间和内核空间,系统为了保护内核数据,会将寻址空间分为用户空间和内核空间,32位机器为例,高1G字节作为内核空间,低3G字节作为用户空间.当用户程序读取数据的时 ...

  6. 简述linux同步与异步、阻塞与非阻塞概念以及五种IO模型

    1.概念剖析 相信很多从事linux后台开发工作的都接触过同步&异步.阻塞&非阻塞这样的概念,也相信都曾经产生过误解,比如认为同步就是阻塞.异步就是非阻塞,下面我们先剖析下这几个概念分 ...

  7. linux基础编程:IO模型:阻塞/非阻塞/IO复用 同步/异步 Select/Epoll/AIO(转载)

      IO概念 Linux的内核将所有外部设备都可以看做一个文件来操作.那么我们对与外部设备的操作都可以看做对文件进行操作.我们对一个文件的读写,都通过调用内核提供的系统调用:内核给我们返回一个file ...

  8. 高性能IO设计模式之阻塞/非阻塞,同步/异步解析

    提到高性能,我想大家都喜欢这个,今天我们就主要来弄明白在高性能的I/O设计中的几个关键概念,做任何事最重要的第一步就是要把概念弄的清晰无误不是么?在这里就是:阻塞,非阻塞,同步,异步. OK, 现在来 ...

  9. Linux下同步模式、异步模式、阻塞调用、非阻塞调用总结

    转自:http://www.360doc.com/content/13/0117/12/5073814_260691714.shtml 同步和异步:与消息的通知机制有关. 本质区别 现实例子 同步模式 ...

  10. 同步异步,阻塞非阻塞 和nginx的IO模型

    同步与异步 同步和异步关注的是消息通信机制 (synchronous communication/ asynchronous communication).所谓同步,就是在发出一个*调用*时,在没有得 ...

随机推荐

  1. Asp.Net应用运行原理

    一.运行原理图 二.对于HttpModule和HttpHandler的概念可能还不是很清楚,请先看Asp.Net应用生命周期.RAR 或者 Asp.Net深入解析 第四章,流程图太大无法粘贴 三.传智 ...

  2. poj3667 线段树 区间合并

    //Accepted 3728 KB 1079 ms //线段树 区间合并 #include <cstdio> #include <cstring> #include < ...

  3. fix eclipse gc overhead limit exceeded in mac

    fix eclipse gc overhead limit exceeded: 在mac上找不到eclipse.ini文件编辑内存限制,在eclipse安装目录右击eclipse程序,选“显示包内容” ...

  4. CentOS中vsftp安装与配置

    http://blog.chinaunix.net/uid-7271021-id-3086186.html 553 Could not create file 解决办法 [root@localhost ...

  5. 黑马程序员——【Java基础】——面向对象(一)概述、类与对象、继承、抽象类、接口、多态、内部类

    ---------- android培训.java培训.期待与您交流! ---------- 一.面向对象概述 1.面向对象:是一个很抽象的概念,它相对面向过程而言,是一种程序设计的思想. 2.面向对 ...

  6. CSS样式选择器

    <!-- css样式选择器 HTML选择器 类选择器 ID选择器 关联选择器 组合选择器 伪元素选择器 selector{ /* selector是样式选择器 property:value; / ...

  7. fibonacci数列(二)_矩阵快速幂

    描述 In the Fibonacci integer sequence, F0 = 0, F1 = 1, and Fn = Fn − 1 + Fn − 2 for n ≥ 2. For exampl ...

  8. C# string格式的日期时间字符串转为DateTime类型

    (1 )Convert.ToDateTime(string) string格式有要求,必须是yyyy-MM-dd hh:mm:ss (2):Convert.ToDateTime(string, IFo ...

  9. Unity3D ShaderLab 修改渲染队列进行深度排序

    Unity3D ShaderLab 修改渲染队列进行深度排序 为了更深刻的理解透明度,我们还需要学习一下深度排序,简单来说就是物体被渲染的先后顺序. Unity允许我们通过代码来控制某个特定物体渲染到 ...

  10. 制作0.5px像素的细条

    <!DOCTYPE html><html><head> <meta charset="utf-8"> <meta name=& ...