作者 | 菜菜

责编 | 郭芮

Y妹:菜菜哥,老大说把所有的接口都改成异步操作......

菜菜:异步好呀,最少比同步能提高吞吐量。

Y妹:异步是怎么回事呢,能讲讲不?

菜菜:来,哥给你解释一番。

异步定义

关于异步的定义,网上有很多不同的形式,但是归根结底中心思想是不变的。无论是在HTTP请求调用的层面,还是在CPU内核态和用户态传输数据的层面,异步这个行为针对的是调用方:

一个可以无需等待被调用方的返回值就让操作继续进行的方法。

在多数程序员的概念中一般是指线程处理的层面:

异步是计算机多线程的异步处理。与同步处理相对,异步处理不用阻塞当前线程来等待处理完成,而是允许后续操作,直至其它线程将处理完成,并回调通知此线程。

可以这样通俗的理解,异步主要解决的问题是不阻塞调用方,用方这里可以是HTTP请求的发起者,也可以是一个线程。

但此处需要明确的是:异步与多线程与并行不是同一个概念。

CPU密集型操作

我听有的同学说,异步解决的是IO密集型的操作,我觉得是不准确的。异步同样可以解决CPU密集型操作,只不过场景有限而已。

有一个前提:利用异步解决CPU密集型操作要求当前运行环境支持多线程才行,比如JavaScript这个语言,本质上它的运行环境是单线程的,所以对于CPU密集型操作,JavaScript会显得力不从心。

异步解决CPU密集操作一般情况下发生在同进程中,为什么这么说呢,如果发生在不同机器或者不同进程在很多情况下已经属于IO密集型的范围了。这里顺便提醒一下:IO操作可不单单是指磁盘的操作,所有有输入/输出(Input/Output)操作的都可以泛称为IO。

举个栗子吧:

在一个带有UI的软件上点击一个按钮,UI线程会发生操作行为,假如UI线程在执行过程中有一个计算比较耗时的操作(你可以想象成计算1--999999999的和),UI线程在同步操作的情况下会一直等待计算结果,在计算完毕之后才会继续执行剩余操作。在等待的这个过程中,呈现给用户的情况就是UI卡住了,俗称假死了,带给用户的体验是非常不好的。这种情况下,我们可以新启动一个线程去执行这个耗时的操作,当执行完毕,利用某种通知机制来通知原来线程,以便原来线程继续自己的操作。

启动新线程执行CPU密集型操作利用的其实就是多线程的优势,如果是单核CPU,其实这种优势并不明显。

IO密集型操作

异步的优势在IO密集型操作中表现的淋漓尽致,无论是读取一个文件还是发起一个网络请求,我的建议是尽量使用异步。

这里首先普及一个小知识:其实每个外设设备都有自己的处理器,比如磁盘,所以每个外设设备都可以处理自己相应的请求操作。但是处理外设设备信息的速度和CPU的执行速度来比较有着天壤之别。

上图展示了不同的 IO 操作所占用的 CPU 时钟周期。

在计算机中,CPU的运算速度最快,以其的运算速度为基准,时钟周期为1。其次是一级缓存、二级缓存和内存,硬盘和网络最慢,它们所花费的时钟周期和内存所花费的时钟周期差距在五位数以上,更不用提跟CPU和一级缓存、二级缓存的差距了。

由于速度的差距,所以几乎所有的IO操作都推荐使用异步。比如当读取磁盘一个文件的时候,同步状态下当前线程在等待读取的结果,这个线程闲置的时间几乎可以用蛋疼来形容。所以现代的几乎所有的知名第三方的操作都是异步操作,尤其以Redis、Nodejs 为代表的单线程运行环境令人刮目相看。

现在是微服务盛行的时代,UI往往一个简单的按钮操作,其实在后台程序可能调用了几个甚至更多的微服务接口(关于微服务这里不展开),如果程序是同步操作的话,那响应时间是这些服务接口响应时间的和,但是如果采用的是异步操作,调用方可以在瞬间把调用服务接口的操作发送出去,线程可以继续执行下边代码或者等待所有的服务接口返回值也可以。

最差的情况下,接口的响应时间为最慢的那个服务接口响应时间,这有点类似于木桶效应。

异步的回调

通过以上介绍,我们一定要记住一个知识点:异步需要回调机制。

异步操作之所以能在执行结果完成之后继续执行下面程序完全归功于回调,这也是所有异步场景的核心所在,前到JS的异步回调,后到CPU内核空间copy数据到用户空间完成通知等等异步场景,回调无处不在。

说道回调大部分语言都是注册一个回调函数,比如JS会把回调的方法注册到执行的队列,C#会把回调注册到IOCP。这里延伸一下,在很多系统里,很多IO网络模型其实是属于同步范畴的,比如多路复用技术,真正异步非阻塞的推荐Windows下的IOCP。

现在很多现代语言都支持更优秀的回调方式,比如JS和C# 现在都支持async 和await方式来进行异步操作。

据说Windows下的IOCP才是真正的异步非阻塞模型,求留言区验证!

异步的特点

优势:

  • 异步操作无须额外的线程负担,使用回调的方式进行后续处理,在设计良好的情况下,处理函数可以不必使用共享变量(即使无法完全不用,最起码可以减少 共享变量的数量),减少了死锁的可能。

  • 线程数量的减少,减少了线程上下文在CPU切换的开销。

  • 微服务环境(调用多个服务接口的情况下)加快了上层接口的响应时间,意味着增加了上层接口的吞吐量。

劣势:

  • 异步操作传统的做法都是通过回调函数来实现,与同步的思维有些差异,而且难以调试。

  • 如果当前环境有操作顺序的要求,异步操作为了保证执行的顺序需要做额外的工作。

  • 由于多数情况下异步的回调过程中的执行线程并非原来的线程,所以在捕获异常,上下文传递等方面需要做特殊处理,特别是不同线程共享代码或共享数据时容易出问题。

写在最后

  • 在并发量较小的情况下,阻塞式 IO和异步IO的差距可能不是那么明显,但随着并发量的增加,异步IO的优势将会越来越大,吞吐率和性能上的差距也会越来越明显。

  • 在压力比较小的情况下,一般异步请求的响应时间大于同步请求的响应时间,因为异步的回调也是需要时间的。

  • 在大并发的情况下,采用异步调用的程序所用线程数要远远小于同步调用程序所用的线程数,CPU使用率也一样(因为避免了太多线程上下文切换的成本)。

为了系统性能,不要让任何设备停下来休息。

作者:菜菜,一个奔走在通往互联网更高之路的工程师,热衷于互联网技术。目前就职于某互联网教育公司,应用服务端主要负责人。拥有10年+互联网开发经验,热衷于高性能、高并发、分布式技术领域的研究,主要工作语言为C#和Golang 。

声明:本文为作者投稿,版权归其个人所有。

【End】

作为码一代,想教码二代却无从下手:

听说少儿编程很火,可它有哪些好处呢?

孩子多大开始学习比较好呢?又该如何学习呢?

最新的编程教育政策又有哪些呢?

下面给大家介绍CSDN新成员:极客宝宝(ID:geek_baby)

戳他了解更多↓↓↓

 热 文 推 荐 

☞ 最强编程语言 Java 和最受欢迎之 Python 的巅峰对决

☞ 技术头条

☞ 淘宝要吃垮拼多多?

☞厉害了!超越 Google,16 岁少女发明眼疾诊断 AI 模型!

☞ 和 996 对着干的百亿巨头:不打卡,不设 KPI,福利好到爆,却称霸行业 20 年!

☞ 回报率29%! 大神用情感分析创建一个比特币交易算法, 原来交易玩的是心理战

☞ 开发者如何写好技术简历?

☞ 写代码这条路,能走多远?阿里算法专家告诉你

☞ 她说:为啥程序员都特想要机械键盘?这答案我服!

System.out.println("点个在看吧!");
console.log("点个在看吧!");
print("点个在看吧!");
printf("点个在看吧!\n");
cout << "点个在看吧!" << endl;
Console.WriteLine("点个在看吧!");
Response.Write("点个在看吧!");
alert("点个在看吧!")
echo "点个在看吧!"

你点的每个“在看”,我都认真当成了喜欢

程序员修神之路:问世间异步为何物?相关推荐

  1. 程序员修神之路--问世间异步为何物?

    菜菜哥,今天天气挺热的,我都穿裙子了 说吧,什么事?? 苦笑一下..... 老大说把所有的接口都改成异步操作 异步好呀,最少比同步能提高吞吐量 异步是怎么回事呢,能讲讲不? 来,凑近一点,哥给你解释一 ...

  2. 多个容器一起打包_程序员修神之路容器技术为什么会这么流行(记得去抽奖)

    菜菜哥,你上次讲的kubernetes我研究了一下,你再给我讲讲docker呗 docker可很流行呀 kubernetes是容器编排技术,容器不就是指的docker吗? docker可不等于容器哦, ...

  3. 程序员修神之路--晦涩难懂的CAP,是否完全正确?

    微信搜一搜 架构师修行之路 菜菜哥,帮忙解决一个问题 是不是面试又被虐了? 是的呢,这次面试官问我什么是CAP? 这个可就说来话长了...... 01 PART CAP 说到CAP,首先不能不说分布式 ...

  4. 程序员修神之路--简约而不简单的分布式通信基石

    点击"蓝字"关注,领取架构书籍 菜菜哥,请教一个问题呗 面试又被卡住了? 还是你了解我呀,tcp协议面向连接是怎么回事呢? 这个说详细起来,那本好几百页的tcp协议的书籍你倒是可以 ...

  5. 程序员修神之路--分布式系统设计理念这么难学?

    点击"蓝字"关注我们吧 福利:有件小事想和大家说一下 菜菜哥,问你个问题,为什么现在的系统都设计为分布式系统呢? 这个问题问得好,就像为什么程序员会慢慢脱发一样神奇 01 PART ...

  6. 程序员修神之路--打通Docker镜像发布容器运行流程

    菜菜哥,我看了一下docker相关的内容,但是还是有点迷糊 还有哪不明白呢? 如果我想用docker实现所谓的云原生,我的项目该怎么发布呢? 这还是要详细介绍一下docker了 Docker 是一个开 ...

  7. 程序员修神之路--容器技术为什么会这么流行(记得去抽奖)

    菜菜哥,你上次讲的kubernetes我研究了一下,你再给我讲讲docker呗 docker可很流行呀 kubernetes是容器编排技术,容器不就是指的docker吗? docker可不等于容器哦, ...

  8. 程序员修神之路--kubernetes是微服务发展的必然产物

    菜菜哥,我昨天又请假出去面试了 战况如何呀? 多数面试题回答的还行,但是最后让我介绍微服务和kubernetes的时候,挂了 话说微服务和kubernetes内容确实挺多的 那你给我大体介绍一下呗 可 ...

  9. 程序员修神之路--高并发系统设计负载均衡架构

    点击上方"蓝字"关注,酷爽一夏 菜菜哥,上次你给我讲的分库分表策略对我帮助很大 有帮助就好,上次请我的咖啡也很好喝~ 呵呵,不过随着访问量的不断加大,网站我又加了nginx做负载均 ...

  10. 程序员修神之路--用NOSql给高并发系统加速

    领取福利 记得长按,领取技术书籍哦 随着互联网大潮的到来,越来越多网站,应用系统需要海量数据的支撑,高并发.低延迟.高可用.高扩展等要求在传统的关系型数据库中已经得不到满足,或者说关系型数据库应对这些 ...

最新文章

  1. 使用二代矫正三代全长转录组数据
  2. 详细透彻的分析DM9000网卡驱动程序(4)
  3. iOS6.0 xcode4.5 设置横屏
  4. CSS3展开带弹性动画的手风琴菜单
  5. 论文浅尝 | HEAD-QA: 一个面向复杂推理的医疗保健数据集
  6. 23种经典设计模式都有哪些,如何分类?Java设计模式相关面试
  7. nginx 重启和配置include的位置
  8. 练习:C#---for循环(整数和、阶乘、楼梯)
  9. mysql搜索中文 有的匹配不出来_MYSQL-中文检索匹配与正则表达式
  10. 【水果识别】基于matlab GUI苹果质量检测及分级系统(带面板)【含Matlab源码 1613期】
  11. 关于VB中Print函数在数组中换行的理解
  12. 微信数据解密-dat查看-免费dat转图片
  13. Hutool excel 设置单元格格式为文本
  14. Upgraded Edition
  15. Valve在Game Dev Conference上,OUYA上的1000场比赛等等
  16. 经典Java开发教程!腾讯+字节+阿里面经真题汇总,斩获offer
  17. Java xml出现错误 javax.xml.transform.TransformerException: java.lang.NullPointerException
  18. Xgen Animwires 随笔01
  19. 简述一下延时函数delay怎么用
  20. 写mall项目报错Tests run: 1, Failures: 0, Errors

热门文章

  1. 动画学习android,Android动画学习
  2. python提高——类(私有化,封装、继承、多态)
  3. 新机发布会用鸿蒙吗,鸿蒙操作系统及华为全场景新品发布会即将到来,硬件生态发展有望迎来加速度...
  4. Flutter基础—定位对齐之中心定位
  5. 内窥镜冲洗装置行业调研报告 - 市场现状分析与发展前景预测
  6. 2021年中国电子设备维修服务市场趋势报告、技术动态创新及2027年市场预测
  7. python中的递归函数是什么_Python中的递归函数是什么
  8. 做游戏,学编程(C语言) 20 扫雷
  9. vs code无法启动怎么解决?
  10. IDEA Maven 聚合项目(多模块)搭建--最精简