CSDN从小白到高手,10 图教你同步与异步( 二 )


CSDN从小白到高手,10 图教你同步与异步
本文插图
【CSDN从小白到高手,10 图教你同步与异步】
在这里 , 你写邮件别人摸鱼 , 这两件事又在同时进行 , 收件人和发件人都不需要相互等待 , 发件人写完邮件的时候简单的点个发送就可以了 , 收件人收到后就可以阅读啦 , 收件人和发件人不需要相互依赖、不需要相互等待 。
你看 , 在这个场景下“不依赖” , “无关联” , “无需等待”这些关键词就出现了 , 因此邮件这种沟通方式就是异步的 。
同步调用
现在终于回到编程的主题啦 。
既然现在我们已经理解了同步与异步在各种场景下的意义(I hope so) , 那么对于程序员来说该怎样理解同步与异步呢?
我们先说同步调用 , 这是程序员最熟悉的场景 。
一般的函数调用都是同步的 , 就像这样:
funcA {// 等待函数funcB执行完成 funcB;// 继续接下来的流程}
funcA调用funcB , 那么在funcB执行完前 , funcA中的后续代码都不会被执行 , 也就是说funcA必须等待funcB执行完成 , 就像这样:
CSDN从小白到高手,10 图教你同步与异步
本文插图
从上图中我们可以看到 , 在funcB运行期间funcA什么都做不了 , 这就是典型的同步 。
注意 , 一般来说 , 像这种同步调用 , funcA和funcB是运行在同一个线程中的 , 这是最为常见的情况 。
但值得注意的是 , 即使运行在两个不能线程中的函数也可以进行同步调用 , 像我们进行IO操作时实际上底层是通过系统调用(关于系统调用请参考《程序员应如何理解系统调用》)的方式向操作系统发出请求的 , 比如磁盘文件读取:
read(file, buf);
这就是我们在《读取文件时 , 程序经历了什么》中描述的阻塞式I/O , 在read函数返回前程序是无法继续向前推进的 。
如图所示:
CSDN从小白到高手,10 图教你同步与异步
本文插图
只有当read函数返回后程序才可以被继续执行 。
注意 , 和上面的同步调用不同的是 , 函数和被调函数运行在不同的线程中 。
因此我们可以得出结论 , 同步调用和函数与被调函数是否运行在同一个线程是没有关系的 。
在这里我们还要再次强调 , 同步方式下函数和被调函数无法同时进行 。
同步编程对程序员来说是最自然最容易理解的 。
但容易理解的代价就是在一些场景下 , 同步并不是高效的 , 原因很简单 , 因为任务没有办法同时进行 。
接下来我们看异步调用 。
异步调用
有同步调用就有异步调用 。
如果你真的理解了本节到目前为止的内容的话 , 那么异步调用对你来说不是问题 。
一般来说 , 异步调用总是和I/O操作等耗时较高的任务如影随形 , 像磁盘文件读写、网络数据的收发、数据库操作等 。
我们还是以磁盘文件读取为例 。
在read函数的同步调用方式下 , 文件读取完之前调用方是无法继续向前推进的 , 但如果read函数可以异步调用情况就不一样了 。
假如read函数可以异步调用的话 , 即使文件还没有读取完成 , read函数也可以立即返回 。
read(file, buff);// read函数立即返回// 不会阻塞当前程序
就像这样:
CSDN从小白到高手,10 图教你同步与异步
本文插图
可以看到 , 在异步这种调用方式下 , 调用方不会被阻塞 , 函数调用完成后可以立即执行接下来的程序 。
这时异步的重点就在于调用方接下来的程序执行可以和文件读取同时进行 , 从上图中我们也能看出这一点 , 这就是异步的高效之处 。


推荐阅读