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

OK, 现在来具体看看。

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

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

所以一般I/O模型可以分为:同步阻塞,同步非阻塞,异步阻塞,异步非阻塞IO。

同步阻塞IO:
在此种方式下,用户进程在发起一个IO操作以后,必须等待IO操作的完成,只有当真正完成了IO操作以后,用户进程才能运行。JAVA传统的IO模型属于此种方式!

同步非阻塞IO:
在此种方式下,用户进程发起一个IO操作以后边可返回做其它事情,但是用户进程需要时不时的询问IO操作是否就绪,这就要求用户进程不停的去询问,从而引入不必要的CPU资源浪费。其中目前JAVA的NIO就属于同步非阻塞IO。

异步阻塞IO:
此种方式下是指应用发起一个IO操作以后,不等待内核IO操作的完成,等内核完成IO操作以后会通知应用程序,这其实就是同步和异步最关键的区别,同步必须等待或者主动的去询问IO是否完成,那么为什么说是阻塞的呢?因为此时是通过select系统调用来完成的,而select函数本身的实现方式是阻塞的,而采用select函数有个好处就是它可以同时监听多个文件句柄(如果从UNP的角度看,select属于同步操作。因为select之后,进程还需要读写数据),从而提高系统的并发性!

异步非阻塞IO:
在此种模式下,用户进程只需要发起一个IO操作然后立即返回,等IO操作真正的完成以后,应用程序会得到IO操作完成的通知,此时用户进程只需要对数据进行处理就好了,不需要进行实际的IO读写操作,因为真正的IO读取或者写入操作已经由内核完成了。目前Java中还没有支持此种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,操作完毕的通知,这可以使进程在数据读写时也不阻塞。(等待"通知")

多路就绪:1.强调多路. 2.只针对请求数据是否就绪.不针对i/o读写
epoll针对的是这样的场景.
select, epoll都只需要进程被动接收到数据就绪"通知".符合异步的定义. 不需要一直在等(同步阻塞).或轮询(同步非阻塞).

总结:  其实阻塞与非阻塞都可以理解为同步范畴下才有的概念,对于异步,就不会再去分阻塞非阻塞。对于用户进程,接到异步通知后,就直接操作进程用户态空间里的数据好了。同步和异步是相对于应用和内核的交互方式而言的,同步需要主动去询问,而异步的时候内核在IO事件发生的时候通知应用程序,而阻塞和非阻塞仅仅是系统在调用系统调用的时候函数的实现方式而已。

同步和异步是相对于应用和内核的交互方式而言的,同步需要主动去询问,而异步的时候内核在IO事件发生的时候通知应用程序,而阻塞和非阻塞仅仅是系统在调用系统调用的时候函数的实现方式而已。

高性能IO设计模式之阻塞/非阻塞,同步/异步解析的更多相关文章

  1. 【转载】高性能IO设计 & Java NIO & 同步/异步 阻塞/非阻塞 Reactor/Proactor

    开始准备看Java NIO的,这篇文章:http://xly1981.iteye.com/blog/1735862 里面提到了这篇文章 http://xmuzyq.iteye.com/blog/783 ...

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

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

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

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

  4. 操作系统介绍-操作系统历史,IO,进程的三态,同步异步阻塞非阻塞

    1.操作系统历史 2.进程,IO,同步异步阻塞非阻塞 操作系统历史: 手工操作: 1946年第一台计算机诞生--20世纪50年代中期,计算机工作还在采用手工操作方式.此时还没有操作系统的概念. 手工操 ...

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

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

  6. (转)同步异步,阻塞非阻塞 和nginx的IO模型

    同步异步,阻塞非阻塞 和nginx的IO模型  原文:https://www.cnblogs.com/wxl-dede/p/5134636.html 同步与异步 同步和异步关注的是消息通信机制 (sy ...

  7. Java IO 学习(一)同步/异步/阻塞/非阻塞

    关于IO,同步/异步/阻塞/非阻塞,这几个关键词是经常听到的,譬如: “Java oio是阻塞的,nio是非阻塞的” “NodeJS的IO是异步的” 但是这些东西听多了就容易迷糊,比方说同步是否就是阻 ...

  8. python并发编程之IO模型 同步 异步 阻塞 非阻塞

    IO浅谈 首先 我们在谈及IO模型的时候,就必须要引入一个“操作系统”级别的调度者-系统内核(kernel),而阻塞非阻塞是跟进程/线程严密相关的,而进程/线程又是依赖于操作系统存在的,所以自然不能脱 ...

  9. 关于IO的同步,异步,阻塞,非阻塞

    上次写了一篇文章:Unix IO 模型学习.恰巧在这次周会的时候,@fp1203 (goldendoc成员之一) 正好在讲解poll和epoll的底层实现.中途正好讨论了网络IO的同步.异步.阻塞.非 ...

随机推荐

  1. c# 循环语句练习题;

    1. 求100以内质数的和 2. 兔子问题 3. 九九乘法表:   一行一行打印: 4. 有一张超大的纸:   纸质的厚度是0.01:   对折多少次,可以达到珠峰的高度:   按照8848来计算: ...

  2. 基于Node.js的强大爬虫 能直接发布抓取的文章哦

    基于Node.js的强大爬虫 能直接发布抓取的文章哦 基于Node.js的强大爬虫能直接发布抓取的文章哦!本爬虫源码基于WTFPL协议,感兴趣的小伙伴们可以参考一下 一.环境配置 1)搞一台服务器,什 ...

  3. Fire Net HDU 1045

    简单深搜,可以完全暴力,不会超时的. #include<iostream> #include<cstring> #include<cmath> using name ...

  4. 【转】文件读写NDK(或Linux)

    原文网址:http://www.ithao123.cn/content-10709539.html 使用NDK进行文件读写,有利于保存数据的安全性,项目需要,要文件读写从Java中处理搬到Linux平 ...

  5. delphi NativeXml的中文支持 乱码

    一般XML的编码格式设置成UTF8比较通用,下面演示使用UTF8编码方式存储和处理包含中文的XML字符串(文件).1.设置启用内置的widestring支持 NativeXml内部使用ANSI str ...

  6. Storm-1.0.1+ZooKeeper-3.4.8+Netty-4.1.3 HA集群安装

    Storm-1.0.1+ZooKeeper-3.4.8+Netty-4.1.3 HA集群安装 下载Storm-1.0.1 http://mirrors.tuna.tsinghua.edu.cn/apa ...

  7. 使用JAVA与SmartFoxServer来实现游戏服务器概述

    SmartFoxServer 是专门为Adobe Flash设计的跨平台socket服务器,让开发者高效地开发多人应用及游戏. 该服务器主要用来创建多玩家游戏.并提供强大的制作工具,各种回合制游戏和实 ...

  8. git 绑定github

    1.创建一个名为git文件夹 2.git init 3.ssh-keygen -t rsa -C "邮箱地址" 4.根据上一步当中默认的文件夹找到id_rsa.pub 复制其中的内 ...

  9. 《HTML5 从入门到精通--7.6.3 单元格垂直跨度——rowspan》

    单元格除了能够在水平方向上跨列,还能够垂直方向上跨行.跨行设置须要使用rowspan參数. 语法 <td rowspan="单元格跨行数"> 语法解释 与水平跨度相相应 ...

  10. Android Fragment生命周期及静态加载

    一个Fragment必须总是被嵌入到一个Activity中,它的生命周期直接被其所属的宿主Activity生命周期影响,它的状态会随宿主的状态变化而变化. 要创建一个Fragment 必须创建一个Fr ...