同步和异步的重点在于多个任务的执行过程中,一个任务的执行是否会导致整个流程的暂时等待。
阻塞和非阻塞着重点在于发出一个请求时,如果进行操作的条件不满足是否会返回一个标志信息告知条件不满足。
同步IO和异步IO模型是针对用户线程和内核线程的交互来说的:
对于同步IO:用户发出IO请求操作之后,如果数据没有就绪,需要通过用户线程(同步非阻塞模型)或者内核(多路复用模型)不断地去轮询数据是否就绪,当数据就绪时,再将数据从内核拷贝到用户线程(这里用户线程阻塞)。
对于异步IO,只有IO请求操作的发出是由用户线程来进行的,IO操作的两个阶段都是由内核自动完成,然后发送通知告知用户线程IO操作已经完成,也就是说异步IO不会对用户线程产生任何阻塞。
所以二者的关键区别反映在数据拷贝阶段是由用户线程完成还是内核完成。异步IO操作必须要有操作系统底层支持。
多路复用模型过程会发起两次系统调用,分别是select和read,在select调用中,用户线程阻塞在select系统调用上,此时内核会不断轮询select的监控对象,当有监控对象数据准备就绪时,用户线程就会继续发起read调用将数据从内核缓存区复制到用户进程缓冲区,此时会阻塞用户线程,内核搬运数据需要cpu参与。通过上述过程可以用一个用户线程来实现监控多个客户端连接请求,但是这里会出现一个问题,就是如果用户线程处理时长太久,会导致其他请求无法得到响应,所以可以通过线程池的方式来缓解这一问题的发生。具体如下图所示(图片来自于参考二):
参考:1.https://mp.weixin.qq.com/s/N2oxGd1xeFHT1lN7LkWCkQ
2.https://mp.weixin.qq.com/s/9YXsJo_u2zVNqvABoGqfqg