BIO,NIO,AIO有什么区别?

2 个回答

  • Rose的肉丝儿
    想多了全是问题,想开了全是答案。
    NIO(同步非阻塞型)和 AIO(异步非阻塞型)是两种 I/O 模型,它们的主要区别在于**数据的处理方式和线程的阻塞与非阻塞行为**。下面我会详细解释两者的差异。 ### 1. **NIO(同步非阻塞型)** NIO 是“同步非阻塞型 I/O”,主要的工作方式是通过多路复用机制(如 `select`、`poll` 或 `epoll`),让一个线程同时处理多个 Socket 连接,线程轮询这些连接,判断哪些连接的数据已经准备好。 #### NIO 工作流程: - **非阻塞**:每个连接的读取/写入操作都是非阻塞的,线程会不断地轮询检查这些连接的数据是否准备就绪。如果有数据准备好,线程就会执行相应的 I/O 操作(比如将数据从内核空间拷贝到用户空间)。如果没有数据准备好,轮询继续进行,不会阻塞线程等待。 - **同步**:虽然 NIO 是非阻塞的,但在数据从内核空间拷贝到用户空间的过程中,调用的线程还是**同步等待**数据拷贝完成。也就是说,线程会亲自执行 I/O 操作,并等待数据传输完成后再继续处理。 在典型的 NIO 模型中,通常只有一个线程同时处理多个连接。这个线程既负责轮询,也负责处理 I/O 操作。它在处理某个连接时会同步等待数据传输完成,然后继续处理其他连接。 #### NIO 的关键点: - 线程不会阻塞等待 I/O 准备完成,但会同步执行数据拷贝的工作。 - 每次 I/O 操作,应用程序需要轮询并主动检查哪些连接的数据已准备好,然后处理这些连接。 ### 2. **AIO(异步非阻塞型)** AIO 是“异步非阻塞型 I/O”,它是 NIO 的进一步升级。AIO 彻底消除了同步等待的概念,系统会在后台完成所有 I/O 操作,包括从内核空间到用户空间的数据拷贝,完成后会通过**回调机制**通知应用程序。 #### AIO 工作流程: - **非阻塞**:和 NIO 一样,AIO 也是非阻塞的。程序无需等待数据准备好后再执行操作。 - **异步**:与 NIO 的主要区别在于,当数据准备好时,应用程序不需要同步执行 I/O 操作,系统会自动完成从内核空间到用户空间的数据传输,传输完成后再通知应用程序。这一过程是异步的,调用线程不需要参与整个传输过程,系统会通过回调通知程序“已经读取完毕,可以处理了”。 #### AIO 的关键点: - I/O 操作完全交给操作系统处理,应用程序可以注册一个回调函数,当 I/O 操作完成时,系统会异步调用这个回调函数通知程序。 - 应用程序不需要自己去轮询检查数据是否准备好,也不需要自己执行数据拷贝,所有的 I/O 操作和等待都由系统异步完成。 ### 核心区别: 1. **同步与异步**: - **NIO 是同步的**:虽然线程不会阻塞等待数据准备好,但一旦数据就绪,线程仍然需要同步执行数据的读写操作并等待传输完成。 - **AIO 是异步的**:I/O 操作由系统异步完成,线程不需要等待传输完成,而是通过回调机制通知操作完成。线程可以在 I/O 操作完成之前去做其他事情,当操作完成时,系统会通知它。 2. **谁负责数据读写?** - **NIO**:数据准备就绪后,线程需要自己执行 I/O 操作(比如从 Socket 读取数据)。线程会同步等待数据传输完成。 - **AIO**:系统不仅会负责监控数据是否准备就绪,还会自动完成数据的读取或写入工作。完成后,它会异步通知线程执行后续处理。 3. **线程效率**: - **NIO**:线程依然需要轮询文件描述符的状态,并同步执行 I/O 操作。在大量连接时,需要更多的 CPU 时间来检查每个连接的状态。 - **AIO**:线程注册一次回调函数后就不再关心 I/O 操作,所有的 I/O 由系统异步完成,线程在收到回调通知时才处理 I/O 操作,效率更高。 ### 类比解释: 可以通过类比打电话来理解这两种模型的差异: 1. **BIO(同步阻塞)**: 这是传统的阻塞式 I/O 模型。打电话时,你必须等待对方接听并完成通话。在这期间,你什么都不能做。 2. **NIO(同步非阻塞)**: NIO 模型下,你打电话时不断地拨打(轮询),查看对方是否接听。虽然你不需要等待对方接听,但你得时不时地检查对方是否准备好接电话。当对方接听了,你必须立即处理通话(数据传输),直到通话结束。 3. **AIO(异步非阻塞)**: AIO 则更加智能。你打了电话,告诉系统:“当对方接听并通话完成时,请通知我。”你无需时刻检查对方是否接电话,只要在电话通了之后处理通话结果,整个过程完全交由系统异步处理。 ### 总结: - **NIO** 是非阻塞的,程序可以不断检查是否有数据准备好,但数据传输的过程仍然是同步的,即线程需要等待数据传输完成。 - **AIO** 是异步非阻塞的,不仅数据准备是非阻塞的,连数据传输的过程也是异步的,应用程序只在数据传输完成时通过回调机制获取结果。 因此,AIO 进一步优化了 I/O 处理流程,极大地减少了线程在 I/O 操作上的等待和 CPU 资源的浪费。
    编辑于 2023-05-02 10:26 •IP属地 美国
    举报
    评论
    收藏

  • 无邪
    鸟随鸾凤飞腾远,人伴贤良品自高。
    一次IO的读操作分为等待就绪和IO操作两个阶段,等待就绪就是等待TCP RecvBuffer里面的数据就绪好,也就是发送方的数据全部发送到网卡里面来,操作就是CPU将数据从网卡拷贝到用户空间。 **BIO(同步阻塞型)** 以Java中的IO方式为例,BIO就是同步阻塞型的IO,当一个Socket连接发送数据过来以后,需要为这个Socket连接创建一个线程,由线程调用Socket的read()方法读取数据,需要先把数据从网卡拷贝到内核空间,再拷贝到用户态的内存空间,在数据读取完成前,线程都是阻塞的。这种IO方式就是比较消耗资源,假设有1000个活跃的Socket连接,需要创建出1000个线程来读取数据,读取时都是阻塞的,每个线程有自己独有的线程栈,默认大小是1M。 **NIO(同步非阻塞型)** nio就是多路io复用,就是一个线程来处理多个Socket连接,节省线程资源。以select为例,就是有一个长度为1024的数组,每个元素对应一个Socket连接,线程轮询这个数据,判断哪个Socket连接的数据是出于就绪状态,此时就将数据拷贝到用户空间然后进行处理。由于IO操作阶段是需要等待数据拷贝到用户空间完成才能返回,所以是同步的。由于每次判断内核中Socket缓冲区的数据是否就绪的函数是直接返回的,如果就绪就返回有数据,不是就绪就返回0,线程不需要阻塞等待,所以是非阻塞的。 **AIO(异步非阻塞型)** AIO就是NIO的升级版,在数据处于就绪状态时,也是异步将Socket缓冲区中的数据拷贝到用户空间,然后执行异步回调函数,所以在IO操作阶段也是异步的。 BIO里用户最关心“我要读”,NIO里用户最关心"我什么时候可以读了",在AIO模型里用户更需要关注的是“什么时候读完了,我可以直接进行处理了”。 [https://zhuanlan.zhihu.com/p/23488863](https://zhuanlan.zhihu.com/p/23488863) [https://www.cnblogs.com/sxkgeek/p/9488703.html](https://www.cnblogs.com/sxkgeek/p/9488703.html) [https://blog.csdn.net/weixin_34378045/article/details/91930797](https://blog.csdn.net/weixin_34378045/article/details/91930797)
    发布于 2022-02-07 10:19 •IP属地 辽宁
    举报
    评论
    收藏