关于Dart中异步、同步与并发的两大疑问
Dart异步与同步函数定义及并发实现疑问解答
根据Dart官方文档,不使用
async和await关键字但返回Future对象的函数属于同步函数(synchronous functions),使用async和await关键字的函数属于异步函数(asynchronous functions)。
疑问1:为何返回Future的同步函数看似有异步特征,async函数反而像同步?
这是混淆了「函数自身的执行方式」和「返回值的异步属性」:
- 返回
Future的同步函数,函数体的执行是完全同步的。调用它时,会立刻执行完所有代码,最后返回一个Future对象(这个对象代表后续的异步任务)。比如:
调用该函数时,Future<String> syncReturnFuture() { // 这里的代码同步执行,不会暂停 print("同步执行函数体"); return Future.delayed(Duration(seconds: 1), () => "结果"); }print语句会立即执行,函数瞬间结束,返回的Future只是一个待完成的异步任务载体,这让你觉得它有“异步感”,但函数本身并没有被异步调度。 - 带
async的异步函数,函数体的执行被编译器改写为异步调度流程。遇到await时,函数会暂停执行,把控制权交还给事件循环,等await的Future完成后再恢复执行。从调用者视角看,它返回的也是Future,但函数内部的执行是被拆分成多个片段,由事件循环调度的——你觉得它“像同步”,是因为await让代码的写法看起来是线性的,但底层是异步调度的。 - 核心区别:同步函数本身是同步执行的,只是抛出了一个异步任务;异步函数的执行流程是异步调度的,
await是让异步代码的写法同步化,而非让函数变成同步执行。
疑问2:单线程Isolate中,await如何实现并发?
Dart的单线程是指单个Isolate内只有一个执行线程,但通过**事件循环(Event Loop)**实现任务的并发调度,原理如下:
- 每个Isolate的事件循环包含两个队列:
- 微任务队列(Microtask Queue):优先级更高,存放优先级高的任务(比如Future的完成回调、
scheduleMicrotask注册的任务),会被优先处理完毕。 - 事件队列(Event Queue):存放普通异步任务(比如I/O操作、定时器、UI事件等)。
- 微任务队列(Microtask Queue):优先级更高,存放优先级高的任务(比如Future的完成回调、
- 当main函数中执行
await someFuture()时:- 首先执行
someFuture(),返回一个Future对象。如果该Future尚未完成,当前的async函数会被暂停,await之后的代码会被注册为这个Future的完成回调。 - 此时,main函数的控制权交还给事件循环,事件循环会继续处理队列中等待的其他任务(比如已经完成的Future任务、定时器任务等),实现任务调度层面的并发——不是多线程并行,而是单线程下的任务交替执行。
- 当
someFuture完成后,对应的回调会被加入微任务队列(或事件队列),等事件循环处理到该回调时,才会恢复之前暂停的async函数,继续执行await之后的代码。
- 首先执行
- 这种模式是非阻塞异步调度,通过事件循环高效切换任务片段,让多个异步任务看起来像是同时执行,本质是串行执行不同的任务单元,只是切换速度足够快,达到并发的效果。
内容的提问来源于stack exchange,提问作者Sehyeong An
相关产品推荐
相关产品推荐

