Loading

同步和异步,阻塞和非阻塞

同步和异步,阻塞和非阻塞-结合一个例子简单说明
对于IO同步和阻塞,好像很多人不理解?

同步 和 异步 指的是:

一个执行流程中每个方法是否必须依赖前一个方法完成后才可以继续执行

假设我们的执行流程中:依次是方法一和方法二

同步指的是调用一旦开始,调用者必须等到方法调用返回后,才能继续后续的行为。
即方法二一定要等到方法一执行完成后才可以执行。

异步指的是调用立刻返回,调用者不必等待方法内的代码执行结束,就可以继续后续的行为。(具体方法内的代码交由另外的线程执行完成后,可能会进行回调)。
即执行方法一的时候,直接交给其他线程执行,不由主线程执行,也就不会阻塞主线程,所以方法二不必等到方法一完成即可开始执行。

同步与异步是从多个线程之间的协调来实现效率差异

阻塞与非阻塞 主要是从 CPU 的消耗上来说:

阻塞就是CPU停下来等待一个慢的操作完成CPU才接着完成其它的事。
非阻塞就是在等这个慢的操作在执行时CPU去干其它别的事,等这个慢的操作完成时,CPU 再接着完成后续的操作
虽然表面上看非阻塞的方式可以明显的提高CPU的利用率,但是也带了另外一种后果就是系统的线程切换增加。增加的CPU使用时间能不能补偿系统的切换成本需要好好评估。

阻塞与非阻塞关注的是线程是否在原地等待

下面都是废话

同步和异步

针对请求的客户端和请求的连接

例如:客户端有一个请求的连接,我要去请求服务器端处理一个数据返回一个结果,但是服务端计算这个结果的过程很长

在同步状态下面,这个连接就要处于一直等待的状态 ==》同步

客户端不想等了,发出请求后就想直接连接返回 ==》异步

在异步状态下客户端实际没有真正得到服务端返回的结果,所以在异步处理请求的方式下面往往还需要有一个消息回写的接口或者服务。待服务端把结果算出来后,再通过另一个消息回写把数据给你

阻塞和非阻塞

针对的是服务端的请求线程,服务端的处理线程

例如:客户端查询一个大数据,那么对于服务器的APP server端可以把它理解为请求线程,而实际数据库查这个数据的过程可以把它理解为处理线程

线程阻塞:在阻塞的情况下面,这个线程不能够去做其他的事情。请求线程要一直处于等待的状态

非阻塞:当请求线程发出请求给处理线程之后,不用一直在那等待,请求的线程可以快速的释放回资源池去处理其他的请求。但这个请求线程每隔10s,20s可能要去轮询下处理线程处理过程有没有完成。有完成后就拿着结果返回到客户端去

小结

同步和异步是针对客户端,针对请求的连接来说的

阻塞和非阻塞是针对服务端,针对请求的线程来说的

四种场景

2*2得到4种场景

假设顾客到餐馆去吃饭,顾客可以理解为请求端或客户端

到餐馆后发现任何一个餐馆既有服务员又有厨师,服务员可以理解为请求线程,厨师理解为处理线程

同步加阻塞

image

顾客点了一个菜,把点的菜交给服务员后,服务员再把点的菜传递给厨师,厨师拿到菜单马上就去做

顾客不能去做其他的事情,服务员把菜传给厨师后服务员也处于等待状态,不能去服务其他的顾客

同步加非阻塞

image

顾客点完菜以后同样不能够去做其他的事情,依然处于同步等待的状态

但这时服务员把菜单拿给后厨以后,服务员可以去服务其他的顾客。同时服务员可能每隔两分钟去问后厨菜是否做好

客户请求端仍然时刻等待,但是请求线程可以灵活的去做其他事情

异步加阻塞

image

点完菜以后,和服务员说自己出去溜达下,菜做好就服务员通知自己

服务员把菜单传给后厨以后,服务员一直在那等着

此时客户端可以灵活的去做其他事情,但请求线程处于绑定的状态

异步加非阻塞

image

作为顾客作为请求端可以灵活地去做其他事情

对于服务员把菜单传到后厨以后她也可以去服务其他顾客

异步下面的关键点

在异步时会启用处理线程端的消息队列

也就是说服务员把菜单传给后厨以后,会放在后厨的台面上面,这就是后厨的处理队列

特别的

当谈到异步时,没有必要去区分异步阻塞还是异步非阻塞

在异步的情况下面线程端阻塞和非阻塞没有意义

其他

异步的行为是增加吞吐量,并不能节省结果的处理时间。

阻塞和非阻塞是在线程层面说的。

面试说法

一个IO的操作可以包含两个部分,第一是发起IO请求,第二是实际的IO读写操作。

阻塞和非阻塞在于第一点,发起IO请求,阻塞和非阻塞其实说的是调用方。阻塞就是发起IO请求后傻等着,中间不能去做其他的事情。反之就是非阻塞。

同步和异步的区别在于第二点,实际的IO读写操作。同步和异步说的是被调用方。如果操作系统帮你完成了请求再通知你那么就是异步,反之就是同步。

posted @ 2023-03-30 14:15  ydssx  阅读(27)  评论(0编辑  收藏  举报