阻塞和非阻塞-数据是否准备就绪
阻塞主要是针对数据是否准备好判断IO会导致的行为
- 阻塞和非阻塞一般是指socket的阻塞和非阻塞模式,从而影响对应socket api行为
- 拿recv举例子,如果socket是阻塞的:
- 如果没有内核接收缓冲区没有数据可以收,recv就会阻塞当前线程执行流,
- 只有有数据可收,recv才会接收数据并返回
- 如果返回的是0或者-1就需要关闭连接
- 如果socket是非阻塞的,recv不管有没有数据都会立即返回,不会阻塞当前线程执行流,当然这个时候需要判断返回值,有三种情况:
- 0正常收到对应字节数内容
- =0对端关闭连接,本端也需要关闭连接
- -1&&erro=EWOULDBOLCK当前内核接收缓冲区没有数据可以收
- 在-1且错误码不是EWOULDBOLCK的情况下,就是真的出错了,需要关闭连接
同步和异步
主要是通过数据收发来判断IO的同步异步行为。但是又分为两种,一种是针对IO的同步和异步,一个应用层并发的同步和异步
- IO的同步和异步–数据的读和写
- 同步:比如recv和send都是同步IO,
- 比如recv如果在有数据来的时候,需要先把数据从内核缓冲区拷贝到应用缓冲区,才会返回,线程才会处理接下来的事情,这个收数据的时间是花费应用的时间
- send也是需要将数据从应用缓冲区拷贝到内核缓冲区才会返回,线程再去处理别的事情
- 异步
- 一般是指使用了特殊的异步API接口,比如linux提供的
aio_read
、aio_write
,是将数据的读写收发交给内核,当内核完成后再通过信号或者回调通知应用,这个时候,应用是不需要花费自己的时间去收发读写数据的,可以做自己的事情,等待通知就可以了
- 一般是指使用了特殊的异步API接口,比如linux提供的
- 同步:比如recv和send都是同步IO,
- 应用层的同步和异步
- 同步: A任务等待B任务完成返回了再继续进行
- 异步: A任务告诉B任务自己感兴趣的事和对应的通知方式,A继续执行自己的逻辑,等待B监听到相应时间发生后通知A了,A才开始处理对应的逻辑
TIP: 在处理IO的时候阻塞和非阻塞都是同步IO,使用使用了特殊的API才是异步IO
- 同步阻塞
- 指的是调用同步IO接口,实现的阻塞模式,比如
int size = recv(阻塞socketfd,buf,buf_len,0)
,recv本身就是同步IO,如果有数据是线程调用recv从内核缓冲区拷贝数据到应用缓冲区,这个过程是同步的,只有等数据取完了,线程才能执行其他任务,但是如果没有数据,recv就是使得线程阻塞
- 指的是调用同步IO接口,实现的阻塞模式,比如
- 同步非阻塞
- 指的调用同步IO接口,实现的非阻塞模式,比如
int size = recv(非阻塞socektfd,buf,buflen,0)
,如果没有数据可以收,recv马上返回,不会阻塞当前线程,如果有数据,recv先要收取数据之后再返回,这个收取数据的过程是同步实现的,浪费的是当前线程的时间。
- 指的调用同步IO接口,实现的非阻塞模式,比如
- 异步阻塞
- 指的是调用异步IO接口(
aio_read
、aio_write
),实现的阻塞模式,阻塞的实现过程,就是调用异步IO的线程阻塞等待异步IO完成的信号通知,并处理相应的业务逻辑 - 本身就是异步,但是又阻塞等待异步结果,一般是没有必要浪费线程资源阻塞等待
- 指的是调用异步IO接口(
- 异步非阻塞
- 再异步阻塞的基础上,调用异步IO的线程不阻塞等待信号通知,而是继续完成剩下的逻辑,等有信号的通知的时候再去处理相应的逻辑