阻塞/非阻塞与同步/异步的区别

阻塞与非阻塞

阻塞与非阻塞说的是调用者

阻塞

调用者一直等待被调用者的返回,别的事情什么也不干

非阻塞

调用者不等待被调用者的返回,调用者可以先去做其他的事情

同步与异步

同步与异步说的是被调用者

同步

被调用者在处理完自己的业务逻辑之后,不会通知调用者(调用者必须一直等着结果,因为同步操作不会主动告诉调用者,自己已经处理完了业务逻辑)

异步

被调用者在接收到调用者的请求后,立马通知调用者已经接到请求了,处理完之后再通过回调等方式通知调用者

例子

  1. 阻塞同步:人守在不会自动报警的烧水壶,人需要主动查看水是否开了
  2. 阻塞异步:人守在会自动报警的烧水壶前,水开了,水壶会自动报警
  3. 非阻塞同步: 人一边玩手机一边烧水,每隔一段时间去主动查看下水是否开了
  4. 非阻塞异步: 人一边玩手机一边使用会自动报警的水壶烧水, 水开了,水壶会自动报警

linux中的五种IO模型

阻塞IO模型

一般表现为进程或线程等待某个条件,如果条件不满足,则一致等待下去。条件满足,则进行下一步操作,如下图
阻塞IO模型
应用进程通过系统调用 recvfrom 接收数据,但由于内核还未准备好数据报,应用进程就会阻塞住,直到内核准备好数据报,recvfrom 完成数据报复制工作,应用进程才能结束阻塞状态

非阻塞IO模型

应用进程与内核交互,目的未达到之前,不再一味的等待,而是直接返回;然后通过论询的方式,不停的去问内核数据准备好了没有,如果某一次轮询发现数据已经准备好了,就把数据拷贝到用户空间中
非阻塞IO模型
应用进程通过recvfrom调用不停的去和内核交互,直到内核准好数据。如果没有准备好,内核会返回error,引用进程在得到error后,过一段时间再发送recvfrom请求。在两次发送请求的时间段,进程可以先做别的事情

IO复用模型

多个进程的IO可以注册到同一个管道上,这个管道会统一和内核进行交互。当管道中的某一个请求需要的数据准备好之后,进程再把对应的数据拷贝到用户空间中
IO复用模型
IO多路转接是多了一个select函数,多个进程的IO可以注册到同一个select上,当用户进程调用该select,select会监听所有注册好的IO,如果所有被监听的IO,如果所有被监听的IO需要的数据都没有准备好时,select调用进程会阻塞。当任意一个IO所需要的数据准备好之后,select调用就会返回,然后进程再通过recvfrom来进行数据拷贝

信号驱动IO模型

应用进程预先向内核注册一个信号处理函数,然后用户进程返回,并不阻塞,当内核数据准备就绪时会发送一个信号给进程,用户进程便在信号处理函数中开始把数据拷贝到用户空间中
信号驱动IO模型

异步IO模型

应用进程把IO请求传给内核后,完全由内核去操作文件拷贝内核完成相关操作后,会发送信号告诉应用进程本次IO已经完成
异步IO模型
用户进程发起aio_read操作之后,给内核传递描述符、缓冲区指针、缓冲区大小等,告诉内核当整个操作完成时,如何通知进程,然后就立刻去做其他事情了。当内核收到aio_read后,会立刻返回,然后内核开始等待数据准备,数据准备好以后,直接把数据拷贝到用户空间,然后再通知进程本次IO已经完成

五种IO模型对比

同步IO模型: 阻塞IO模型,非阻塞IO模型,IO复用模型,信号驱动IO模型这四种都是同步的,因为他们虽然在数据准备阶段有的是异步的,有的是同步的,但是在通过recvfrom将数据从内核复制到用户空间的时候都是同步的,故认为他们都是同步的
异步IO模型:异步IO模型是异步的,因为内核在将数据拷贝到用户空间之后再通知进程本次IO已经完成。如下图所示
五种IO模型对比

java中的IO模型

BIO

BIO (Blocking I/O): 同步阻塞I/O模式,数据的读取写入必须阻塞在一个线程内等待其完成。
例子:有一排水壶在烧开水,BIO的工作模式就是,让一个线程停留在一个水壶那,直到这个水壶烧开,才去处理下一个水壶

NIO

NIO (New I/O): 同时支持阻塞与非阻塞模式,但主要是使用同步非阻塞IO。
例子:有一排水壶在烧开水, NIO的工作模式是让一个线程不断的轮询每个水壶的状态,看看是否有水壶的状态发生了改变,从而进行下一步的操作;而主线程可以去做其他的事情

AIO

AIO (Asynchronous I/O): 异步非阻塞I/O模型。
例子: 有一排水壶在烧开水, AIO的工作模式是为每个水壶上面装了一个开关,水烧开之后,水壶会自动通知进程水烧开了