You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

关于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)**实现任务的并发调度,原理如下:

  1. 每个Isolate的事件循环包含两个队列:
    • 微任务队列(Microtask Queue):优先级更高,存放优先级高的任务(比如Future的完成回调、scheduleMicrotask注册的任务),会被优先处理完毕。
    • 事件队列(Event Queue):存放普通异步任务(比如I/O操作、定时器、UI事件等)。
  2. 当main函数中执行await someFuture()时:
    • 首先执行someFuture(),返回一个Future对象。如果该Future尚未完成,当前的async函数会被暂停,await之后的代码会被注册为这个Future的完成回调。
    • 此时,main函数的控制权交还给事件循环,事件循环会继续处理队列中等待的其他任务(比如已经完成的Future任务、定时器任务等),实现任务调度层面的并发——不是多线程并行,而是单线程下的任务交替执行。
    • 当someFuture完成后,对应的回调会被加入微任务队列(或事件队列),等事件循环处理到该回调时,才会恢复之前暂停的async函数,继续执行await之后的代码。
  3. 这种模式是非阻塞异步调度,通过事件循环高效切换任务片段,让多个异步任务看起来像是同时执行,本质是串行执行不同的任务单元,只是切换速度足够快,达到并发的效果。

内容的提问来源于stack exchange,提问作者Sehyeong An

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 21:55:21