通常情况下,代码/指令是会按固定顺序,依次执行的。前面的代码没有执行完毕,后面的代码就无法执行:这就是同步(sync)执行。
如果代码可以/可能会不按书写顺序依次执行,就被称之为异步(async)执行。
PPT演示:
注意:异步强调的是代码的执行顺序,至于代码被谁执行,不重要。
那为什么会出现异步呢?典型的就是因为并行/并发
PPT演示:就像几个人赛跑一样……于是很多同学会认为:
其实不对。
还是上面的例子,
认识到这一点非常重要,不然后面的学习就容易懵。
总结一下(具体到开发):
很多时候异步是(因为并发)被动产生的,但有时候我们却会主动的使用异步。
生活中的例子:顾客在银行窗口排队办理某项业务。
接下来当顾客A填完表格后,可能B、C、D……的业务都处理完了。
原来排队的顺序是:A-B-C-D,但现在变成了A-C-D-B,这是不是就是异步?
窗口对应线程,只有一个,所以还是单线程。
计算机运行也可以这样,后面我们要学习的JavaScript的Ajax技术就是典型的单线程异步:所有的Ajax请求扔到最后处理。
Ajax单线程的异步简单粗暴,类似于上述银行排队例子:A要填表格,那就让开,填完表格重新排队 —— 这样就不太人性化。
可不可以A填完表格之后就回到队伍中,继续办理业务呢?
可以是可以,但让计算机来处理这事,就比较麻烦了……
我们把排队的顾客想得机械/野蛮一些,A填完表格想C的插队,C眼一瞪:凭啥?!
所以我们大概还需要一个额外的“调度员”来进行管理,大家都听他的,他来维持次序,他的工作就相当相当的复杂,大致会有:
这些都是线程调度的状态(略)
另外,很多时候,下一个步骤的执行,是需要上一个步骤的执行结果的。就比如炒菜之前先要切菜
一堆的问题,非常的麻烦……
你以为的多线程,实际上的多线程(缺图)
正如我们前面所说,线程A继续工作(炒菜下锅),需要线程B的结果(切好的菜),但此时线程B还没有完成,线程A只能等待。
那么,A在等待的时候:
你肯定觉得非阻塞的选项2效率更高。实际上我们主动使用异步的时候,通常使用非阻塞的异步。
异步要真正的提高性能(让任务被更快的执行完成),归根结底还是要降低CPU的闲置:在等待I/O结果的时候,让CPU做其他事情。
以前要实现这种效果,开发人员写代码就得新开线程。但后来各种语言(我知道的是从C#开始)纷纷推出了异步方法,你直接标记一个方法为异步,这个方法就自然异步执行,语法上非常简洁,更关键的是,文档里特别强调:异步方法不一定会新开一个线程。
what?
查阅了一些文档,其关键在于:
DMA(Direct Memory Access),即直接存储器访问。拥有DMA功能的硬件在和内存进行数据交换的时候可以不消耗CPU资源。
完美的异步硬件基础!
思考我们现实生活中有哪些并行/并发、同步/异步执行、阻塞/非阻塞的例子:
注意将他们同CPU、进程/线程、I/O等对应起来。
多快好省!前端后端,线上线下,名师精讲
更多了解 加: