当我们谈论IO模型时,我们指的是计算机在进行输入和输出操作时的工作方式。常见的IO模型包括传统的同步阻塞IO(Blocking IO,BIO),同步非阻塞IO(Non-blocking IO,NIO),和异步非阻塞IO(Asynchronous IO,AIO)。这些模型描述了在进行IO操作时,程序如何与设备进行交互以便获取或传输数据。
讲解之前先给大家说明一下 阻塞/非阻塞 和 同步/异步 的意思
阻塞(Blocking):在阻塞操作中,当一个线程执行一个调用时,它将一直等待,直到完成或返回结果。在这个等待过程中,线程处于非活动状态,程序流程无法继续执行其他操作。阻塞操作会占用线程资源,直到操作完成才能释放线程。
非阻塞(Non-Blocking):在非阻塞操作中,当线程执行一个调用时,不会等待操作的完成或结果的返回。线程会立即返回,并继续执行其他操作。非阻塞操作通常通过轮询或回调机制来监视操作的状态,并在操作完成后进行处理。
同步(Synchronous):在同步操作中,调用方发起一个操作请求,并阻塞线程直到操作完成并返回结果。在同步调用中,调用方必须等待操作的完成,然后继续执行后续代码。同步操作通常是阻塞的,因为线程将被挂起直到操作完成。
异步(Asynchronous):在异步操作中,调用方发起一个操作请求,但不会等待操作的完成或结果的返回。相反,它会立即返回,并允许调用方继续执行后续代码。异步操作通常使用回调、事件处理或轮询机制来处理操作的完成通知和结果。
总结:
- 阻塞和非阻塞描述了线程在等待操作完成时的状态和行为。
- 同步和异步描述了调用方与被调用方之间的通信方式和操作的执行方式。
BIO
阻塞IO是最传统的IO模型,它在进行IO操作时会阻塞整个程序,直到数据准备完毕或传输完成。在阻塞IO中,当一个IO操作发生,程序会被阻塞,一直等到该IO操作完成。这意味着程序在进行IO操作时无法做其他任务,必须一直等待数据的准备或传输完成。
例如:想象一下你去餐厅吃饭。在传统的餐厅中,你点了一份菜,厨师开始烹饪。在这个过程中,你会被阻塞(等待)。直到厨师完成烹饪并将菜品送到你的桌子上,你才能继续享用这道菜。在这个例子中,你是调用方,厨师是被调用方,你的等待时间就是阻塞的过程,直到操作(烹饪)完成。
NIO
非阻塞IO模型允许程序进行IO操作时继续执行其他任务,而不需要一直等待。当进行一个IO操作时,如果数据没有准备好或无法立即传输,程序会立即返回,而不会阻塞等待。程序可以通过轮询或选择器(Selector)来检查IO操作是否已完成,如果未完成可以进行其他任务。
实际上这个非阻塞IO模型处于一个"忙等待"的轮询状态,并没有提升进程的性能
例如:在传统的情况下(BIO),你到达公交车站后,你会加入一个长队伍中等待公交车的到来。在这个过程中,你被阻塞(等待),直到你到达队伍的最前面并上车。
然而,如果我们使用NIO,情况会有所不同。公交车站引入了一种非阻塞IO的方式来进一步提高效率。在这个新的模式下,你可以获取一个候车号,然后在公交车站的等候区找个舒适的位置坐下来。你不再需要像传统的BIO模式那样一直站立或等待。当公交车到达时,系统会通过呼叫电子显示屏或广播等方式通知你的候车号已经到了,你可以立即前往上车点。这样,你可以在等待过程中自由地进行其他活动,而不必一直保持注意力的集中或处于阻塞状态。
AIO
异步IO模型与非阻塞IO类似,但是它不需要程序轮询或选择器来检查IO操作的状态。在异步IO中,当执行一个IO操作后,程序会继续执行其他任务,而不需要等待该IO操作完成。IO操作完成后,系统会通知程序,并提供数据给程序处理。
例如:想象一下你使用一个外卖应用来订购外卖。你发送了订单后,不需要一直等着,而是可以继续做其他事情,如继续工作或看电视。一段时间后,你会收到通知,告诉你外卖已经送达并在门外等待。在这个例子中,你发送订单后就可以进行其他操作,直到外卖送达的通知到达,这种方式更像是异步的过程。
每种IO模型都有其适用的场景和优势,选择适合自己需求的IO模型能够提高程序的性能和效率。