阻塞非阻塞/同步异步理解

279 阅读5分钟
两者定义的针对目标不同,异步同步是针对响应本身的,阻塞非阻塞是针对请求本身的。
异步/同步: 指应答模式,服务提供者消息通知的行为。同步是需要调用者一直等待结果或者不断轮询。异步是通过消息通知。同步表示必须等待结果返回,不断轮询再进行下一步的动作(轮询期间可以做其他事)。异步是指不需要等待结果,先去完成其他事务,结果返回后回调通知。
阻塞非阻塞:调用者等待消息的行为,等待消息时,是否挂起当前线程。

同步和异步的概念描述的是用户线程与内核的交互方式:同步是指用户线程发起IO请求后需要等待或者轮询内核IO操作完成后才能继续执行;而异步是指用户线程发起IO请求后仍继续执行,当内核IO操作完成后会通知用户线程,或者调用用户线程注册的回调函数。
阻塞和非阻塞的概念描述的是用户线程调用内核IO操作的方式:阻塞是指IO操作需要彻底完成后才返回到用户空间;而非阻塞是指IO操作被调用后立即返回给用户一个状态值,无需等到IO操作彻底完成。
请求分请求调用者和服务提供者
阻塞非阻塞指的是请求调用者的行为,如果请求后立即返回则是非阻塞,如果需要一直等待请求结果,调用者无法执行后续操作,则是阻塞
同步异步指的是服务提供者处理的能力,如果请求者不需要等待服务提供者的任务完成才算完成。即请求者不需要依赖于服务提供者,只要自己完成了就算任务完成。就是异步,否则请求者依赖于服务提供者的任务完成后,自己才算完成任务,就是同步。
io请求原本分为两部分,一部分是从磁盘拷贝到内核空间,一部分是从内核空间复制到用户空间。
如果两部分是分开的,请求者通过系统调用recvfrom后,内核开始准备数据,从磁盘通过CMA拷贝到内核空间,这一过程是需要花费时间的,所以并不是马上完成,此时如果是阻塞,调用者则一直等待到内核完成上述两部分才返回,如果是非阻塞,则第一过程调用者立马返回,但是返回的是error状态。随后调用者需要通过不断轮询系统调用问内核数据拷贝到内核空间没,轮询过程中,调用者线程可以去做其他事情。如果轮询时内核准备好数据了,则继续系统调用read()将数据从内核空间拷贝到用户空间,这一步是服务提供者内核做的。这个复制过程,调用者是阻塞的。这两个过程,调用者需要依赖服务提供者将数据准备好后,再调用服务提供者去将数据拷贝到用户空间才算完成任务。
如果两部分是一起的,内核空间把这两部分一起做了。调用者通过系统调用后询问数据是否准备好,此时如果是阻塞,则调用者一直等待,但服务提供者内核把数据从磁盘通过CMA拷贝到内核空间,再从内核空间拷贝到用户空间,然后再通知调用者(通过回调或消息通知),此时调用者一次系统调用后,任务就算完成。他是不需要等待被依赖的任务完成,只是通知被依赖的任务要完成什么工作,依赖的任务也立即执行,只要自己完成了整个任务就算完成了。至于被依赖的任务最终是否真正完成,依赖它的任务无法确定。如果此时是非阻塞,则调用者立马可以做其他事,此次读取数据相当于已经完成,所有过程交给了服务提供者内核去完成。内核完成后通过回调或者消息通知调用者。
所谓的同步和异步其实是围绕IO进行的,如果没有io所有都是同步。
一次io分两个步骤:
1.发起io请求
2.实际的处理io请求
阻塞非阻塞区别第一步是否被阻塞,阻塞调用调用者一直等待,不能做其他事,相当于线程挂起。
同步异步区别第二步是否阻塞,如果异步,则所有操作都是服务提供者完成,调用者可以做其他事,并且不需要依赖于服务提供者。(从磁盘拷贝到内核空间,和从内核空间复制到用户空间都是服务提供者完成)。否则如果从内核空间复制到用户空间这一步需要调用者进行系统调用,这一步是阻塞的,调用者依赖于服务提供者上一步的数据准备好(磁盘拷贝到内核空间)才能进行下一步,即为同步。
同步阻塞:调用者发起请求后,挂起线程不能做其他事一直等待结果
同步非阻塞:调用者发起请求后,不需要等待。然后通过轮询问服务提供者是否准备好,轮询期间可以处理其他事情,如果未准备好,则服务提供者立即返回,如果准备好,则返回结果。
异步阻塞:调用者发起请求后,挂起线程一直等待。服务提供者完成了所有事情后,通过消息通知或者回调给调用者,此时调用者才返回。
异步非阻塞:调用者发起请求后,立即返回。服务提供者完成了所有事情后,通过消息通知或回调给调用者。调用者全程可以做其他事情。不依赖于服务提供者。