zoukankan      html  css  js  c++  java
  • 也谈堵塞、非堵塞、同步、异步

    近期在招聘中,发现不少人对BIO、NIO、AIO等理解非常模糊,认为有必要写文章来纠正下非常多人的误解。
    在谈这些之前,非常有必要先介绍下Unix 5种IO模型:
    堵塞:
    堵塞是最经常使用的IO模型,默认情况下全部的文件操作都是堵塞的。以套接字编程为例。在进程空间中调用recvfrom。其系统调用直到数据报文到达且被复制到应用程序进程的缓存区(或者错误发生)后才返回,期间一直在等待。

    进程在从调用recvfrom開始到它返回的整段时间内是被堵塞的。有一张非常经典的图:
    堵塞IO模型
    非堵塞:
    调用recvfrom从应用层到内核的过程中,假设该缓冲区没有数据的话,则直接返回一个EWOULDBLOCK的错误,通常会轮询的进行检查状态,看内核空间有没有数据来。

    直到有数据,最后完毕拷贝。

    例如以下图:
    非堵塞IO模型
    IO多路复用:
    Linux系统提供的select/poll/epoll,进程将一个或者多个FD(文件描写叙述符)传递给一个或者多个poll/select系统调用,堵塞在select。

    select和poll能够帮助侦听非常多的FD是否准备就绪。可是,select和poll是顺序扫描去检查FD的就绪状态。效率比較低,并且支持的FD数量有限(没记错的话,默认好像是1024还是2048。详细记不清)。而epoll是通过事件驱动的方式,当有FD准备就绪的时候,马上回调函数rollback。如图:
    IO多路复用模型
    谈到epoll,不得不提一个经典的问题。apache和nginx的对照。为什么nginx比apache效率高非常多,这就是根本的原因。
    信号驱动:
    这样的模型在实际应用的非常少,这里不做过多介绍,能够看图:
    信号驱动的IO模型
    异步:
    告知内核启动某个操作。并让内核在整个操作完毕后(包含将数据从内核空间复制到自己的缓冲区)通知。异步IO的主要特点是完毕操作后主动通知。如图:
    异步IO模型

    好,上面的可能有点抽象。以下用通俗点的语言来总结一下堵塞,非堵塞。同步,异步
    堵塞,非堵塞:进程/线程要訪问的数据是否就绪,进程/线程是否须要等待;
    同步,异步:訪问数据的方式,同步须要主动读写数据。在读写数据的过程中还是会堵塞;
    异步仅仅须要I/O操作完毕的通知。并不主动读写数据,由操作系统内核完毕数据的读写。


    再举个网上流传的,非常easy理解的样例:
    老张爱喝茶。废话不说。煮开水。
    出场人物:老张。水壶两把(普通水壶。简称水壶;会响的水壶。简称响水壶)。
    1 老张把水壶放到火上,立等水开。(同步堵塞)老张认为自己有点傻
    2 老张把水壶放到火上,去客厅看电视,时不时去厨房看看水开没有。(同步非堵塞)
    老张还是认为自己有点傻,于是变高端了。买了把会响笛的那种水壶。

    水开之后,能大声发出嘀~~~~的噪音。
    3 老张把响水壶放到火上。立等水开。(异步堵塞)老张认为这样傻等意义不大
    4 老张把响水壶放到火上,去客厅看电视,水壶响之前不再去看它了,响了再去拿壶。(异步非堵塞)老张认为自己聪明了。
    所谓同步异步。仅仅是对于水壶而言。普通水壶,同步;响水壶。异步。尽管都能干活,但响水壶能够在自己完工之后,提示老张水开了。

    这是普通水壶所不能及的。


    同步仅仅能让调用者去轮询自己(情况2中),造成老张效率的低下。

    所谓堵塞非堵塞,仅仅对于老张而言。

    立等的老张。
    堵塞。看电视的老张。非堵塞。

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

  • 相关阅读:
    java程序员面试笔记宝典 note
    JVM常见面试题
    面试&笔试总结 数据库、网络协议、常识
    面试&笔试总结 Java框架篇
    面试准备&总结-Java基础篇
    JDBC事务管理及SavePoint示例
    JSP的内置对象
    Java中的集合框架
    .NET WEBAPI 添加中英文切换,国际化项目
    搜索引擎入门 (建立一个简单的java Lucene实例)
  • 原文地址:https://www.cnblogs.com/gccbuaa/p/7219157.html
Copyright © 2011-2022 走看看