引文
我们从这样一个故事开始。某天午饭时间,大家聊得正嗨。
小A突然来了一句:“我X,这傻缺网站支付太慢了,等圈圈转了半天。最后告诉我连接银行接口支付失败,你不能做成异步啊。先告诉我成功,有支付结果再通知我,害的我等了半天”。
新来的同事小B弱弱的问了句:“哥,什么是异步啊?”
前端小C:“异步就是回调。”
小A补充说:“异步就是多线程。”
小C似懂非懂地看着我。
我啃了一口鸡腿:“嗯,他俩说的都对,又都不对。如果安卓的小D在,他可能会说异步不就是事件监听嘛。”
瞬间三人同时盯着我,说的好像很高深,你给解释解释啊。
其实要想理解什么是异步,很简单。凡是要用辩证的眼光要看待。我们先来看看什么是同步。
同步
同步是指用户在进行某个操作之后,暂停下一步操作,直到本次操作结束返回,期间持有的资源也一直占用。
举个栗子:
很久以前,还没有手机的时候。老一辈处对象,想聊聊天只能打电话,每次一打就是几个小时。期间只能对着电话你一句,我一句地呱啦呱啦说一通,啥也不能干。
我们聚焦在聊天这件事上,通过电话来聊天就是一个同步事件,聊天的双方,你一言我一语,交替进行。从一方一看,我说一句,必须等对方应答,我才能说下一句。这里电话就是竞争的资源,一个使用,其他人就不能使用。
异步
接下来,异步概念闪亮登场。什么是异步?异步可以理解为同步的对立面。
我们来想一下,有什么样的方式让两人之间可以不用你一言,我一语地等待,同时不依赖于仅有的电话资源呢。
你可能想到了写信。是的,在那个年代的确是通过写信来解决的。以当时的物价来衡量的化,打电话还是很昂贵的。所以自然而然的就可以通过写信来解决。
通过写信的方式 ,两个人不必等待。我可以把我想对你说的话一股脑全部写到信里。然后偷到邮箱,剩下的就是满心欢喜的期待,等待你的回信。
等待的时间里我可以学学三弦,拉拉京胡,京剧走起。既丰富了生活,又陶冶了情操。如果十天半月收不到回信,我就再写一封。貌似生活野蛮惬意的。
和上面的同步相比,这就是异步。
小B觉得更懵了,这不就是说写信比打电话更适合,异步比同步好吗?那我们是不是在倒退啊。
回到我们之前的观点,凡事看问题,都要从两面性出发。同步和异步的使用也是分场景的,不同的业务场景使用不同的技术。
譬如,在实时性要求比较高的场景下,譬如数据库操作,我们需要使用同步。
再举个例子:
现在你和女朋友闹别扭,你俩都要掰了,要黄了,你还在写信,慢慢腾腾的。等她收到信,估计你是没希望了。这时候,你可定不计较金钱、时间,终极目标就是在最短时间内挽回这段美好的爱情。
相比而言,使用写信的方式,更经济,占用的资源少,双方也有更大的自有,不必完全拘泥于这件事,专业术语来讲叫强耦合,强关联,但是等到对方的回应很慢,有时候邮差把新建弄丢了,可能这辈子都收不到这份回信。而打电话,更直接,相对而言花销大,双方只能一直捧着电话叽叽歪歪,但是可以立马获得对方的甜言蜜语。
那是不是异步一定就比同步的慢呢?还是那句话,要看具体的业务场景,以及具体使用的技术而定而定。譬如在上述的异步情况下,我们可以使用微信语音。同样是异步,但是速度却可以接近近实时。
我们简单总结一下,同步需要等待结果返回,会相对占用资源。异步可以先于真实的结果返回,不需要等待,操作完车后释放资源,不占用竞争资源。
# 异步的使用场景:
那在什么情况下我们需要使用异步呢?
1.任务执行可以不按顺序,即没有特定的时序性或顺序性;
2.操作需要耗费资源,譬如I/O操作,网络请求;
3.不存在共享资源的互斥访问;
4.对于实时性要求不是很高;
5.对核心任务影响不大;
5.非原子性操作;
6.非强一致性操作
异步的好处
那么使用异步有什么好处呢?
可以并发或并行执行非顺序性任务,提高执行效率;
节省资源,业务低耦合,获取更好的用户体验;
避免资源的竞争访问,避免阻塞,避免死锁;
延迟返回,提高请求的响应率
异步的实现
好了,最后我们回到最初问题的讨论,我们来看看大家关于问题的讨论。
小C:“异步就是回调。”
小A:“异步就是多线程。”
在我们理解了什么是异步之后我们会发现,他俩说的都对,前端的回调,或是多线程,以及事件监听,都是异步编程的提现,都能实现一定程度的异步。
但是异步并不止于此,他更多的是一种思想。上述只是他在不同语言,不同业务场景的落地。
其实他还有更多的实现。
我们从一个大的宏观的角度来看,从服务、系统的层面,每一个服务都是一个异步编程提现,譬如微服务体系中的每一服务;
我们从具体服务的架构上来看也是存在异步的,譬如我们常使用的各种中间件,消息队列MQ,
我们通过MQ将生产者和消费者相互隔离开,生产者只关心生产,消费者只关心消费;
我们再从具体的业务实现来看也是有异步的,譬如使用的业务回调,注册推送等;
再比如实现的各种语言也都有不同的异步实现,譬如C的pthread,java的多线程,python的threading,async/wait,golang的gorutine等等。
还有各种编程框架,netty,Akka,flask,C语言的libUV库等等;
甚至经典的操作系统I/O多路复用模型select,poll,epoll等等。
异步可以说无处不在。
听了我的话,他们三人若有所思的点点头。最后我要说的是,异步更重要的是一种思想,而不是特定的实现。