当前位置: 首页 > news >正文

【Rust】16-async/await、Future 与执行器模型

async/await、Future 与执行器模型

研究目标

  • 理解 Rust async 不是创建线程,而是生成状态机。
  • 掌握FutureWaker、executor 的基本关系。
  • 知道 async 代码中所有权、生命周期和 Send 约束为何常见。

async 的核心模型

Rust 的async fn会返回一个实现了Future的值。调用 async 函数本身并不会立即执行完整逻辑,它只是构造一个 future。

asyncfnfetch()->String{String::from("data")}fnmain(){letfuture=fetch();// future 还没有被执行到完成}

future 必须被执行器轮询,才会向前推进。常见执行器包括 Tokio、async-std、smol,也可以在测试或嵌入式环境中使用专门执行器。

Future Trait

简化后的Futuretrait 可以理解为:

usestd::pin::Pin;usestd::task::{Context,Poll};traitFuture{typeOutput;fnpoll(self:Pin<&mutSelf>,cx:&mutContext<'_>)->Poll<Self::Output>;}

poll返回两种状态:

  • Poll::Ready(value):计算完成。
  • Poll::Pending:暂时不能完成,稍后再来轮询。

执行器反复轮询 future。当 future 因等待 IO、定时器或其他事件无法继续时,返回Pending,并通过Waker告诉执行器将来什么时候再唤醒它。

await 做了什么

.await会在当前 future 内等待另一个 future 完成:

asyncfnhandle()->usize{lettext=read_text().await;text.len()}asyncfnread_text()->String{String::from("hello")}

编译器会把handle转换成状态机。read_text().await是一个可能暂停的位置。暂停时,当前函数的局部变量需要被保存到 future 对象内部,等唤醒后继续执行。

async 状态机

可以把 async 函数想象成枚举状态机:

enumHandleFuture{Start,WaitingReadText,Done,}

真实生成代码更复杂,但关键直觉是:跨越.await的局部变量会成为 future 状态的一部分。这也是为什么 async 代码经常遇到所有权和生命周期问题。

Pin 的作用

某些 future 内部可能自引用:状态机里一个字段引用另一个字段。这样的对象一旦被移动,内部引用就可能失效。Pin用于表达“这个值不能再被随意移动”的约束。

普通用户很少需要手写Pin,但理解它有助于解释为什么Future::poll的接收者是Pin<&mut Self>。async/await 让这些复杂性大多被编译器和运行时封装起来。

Waker 与唤醒

当 future 返回Pending时,它必须确保在将来可以继续时调用 waker:

executor poll future future waits for IO future stores waker future returns Pending IO ready waker wakes task executor polls future again

如果 future 返回Pending但没有正确安排唤醒,任务可能永远卡住。执行器和 IO reactor 的配合负责处理这些细节。

执行器模型

执行器负责调度任务。一个常见模型是:

  1. 任务队列保存可运行 future。
  2. 执行器 poll 某个任务。
  3. 如果 Ready,任务完成。
  4. 如果 Pending,任务让出执行权。
  5. 外部事件通过 waker 把任务放回队列。

这和操作系统线程不同。async 任务通常是协作式调度:只有在.await等挂起点才会让出执行权。一个没有 await 的长 CPU 循环会阻塞同一执行器线程上的其他任务。

Tokio 示例

#[tokio::main]asyncfnmain(){lettask=tokio::spawn(async{"hello"});letresult=task.await.unwrap();println!("{result}");}

tokio::spawn通常要求 future 是Send + 'static,因为任务可能在线程池中被移动到其他线程执行,并且执行器不能依赖当前栈帧里的短生命周期引用。

Send 约束常见来源

下面的模式容易出问题:

usestd::rc::Rc;asyncfnwork(){letvalue=Rc::new(1);some_async().await;println!("{value}");}asyncfnsome_async(){}

Rc<T>不是Send。如果value跨越.await存活,那么整个 future 可能不是Send。在多线程执行器中,这类 future 不能被spawn

修复方式取决于需求:

  • 使用Arc<T>替代Rc<T>
  • 让非 Send 值不跨越.await
  • 使用单线程执行器或spawn_local

async 与借用

跨 await 持有借用也需要谨慎:

asyncfnprint_later(text:&str){wait().await;println!("{text}");}asyncfnwait(){}

这个 future 的生命周期依赖text。如果要把它放入要求'static的任务中,就不能借用当前栈上的字符串。常见做法是传入拥有所有权的StringArc<str>

阻塞操作

async 代码中不能随意执行阻塞操作:

std::thread::sleep(std::time::Duration::from_secs(1));

这会阻塞执行器线程。应使用运行时提供的异步版本:

tokio::time::sleep(std::time::Duration::from_secs(1)).await;

文件 IO、数据库驱动、HTTP 客户端也应选择 async 兼容版本,或者放到专门的 blocking 线程池。

常见误解

  • async fn调用后不会自动跑完,必须被 await 或 spawn。
  • async 不等于并行;它主要解决等待期间让出执行权。
  • .await是可能暂停点,跨越它的变量会影响 future 类型。
  • Send + 'static错误通常来自任务调度模型,不是编译器无理限制。

继续研究

  • Rust Async Book:Future、task wakeups、executor。
  • Rust Reference:async functions、async blocks、await expressions。
  • Tokio 文档:runtime、task、spawn、spawn_blocking。
  • futures crate:FutureExt、Stream、select、join。

后记

2026年6月11日15点21分于上海。

http://www.jsqmd.com/news/997633/

相关文章:

  • 搬家寄快递这样打包,省钱又省心 - 快递物流资讯
  • Python实现的朴素贝叶斯邮件分类器,含训练样本与可运行代码
  • 从SIM卡到NFC支付:TLV编码如何悄无声息地支撑你的日常生活?
  • Vivado功耗报告实战:从布线后数据到散热设计的完整解读
  • 动手实现第一个桥接:从接口到具体类
  • 2026 天津黄金回收龙头|收的顶高价回收稳居行业前列 - 奢侈品回收评测
  • 20244118李玺实验四
  • 【Rust】17-Send、Sync 与并发安全抽象
  • 2026拼多多代运营公司推荐:百亿补贴+拼便宜组合拳,销量利润双增长 - 百推信源
  • MATLAB刀具路径B样条拟合与拐点平滑衔接工具包
  • 2026 年 6 月最新|靠谱台车式退火炉源头厂家推荐,非标定制节能热处理炉优选 - 商业新知
  • 2026年通辽装修公司深度对比:全屋定制硬核差距惊人拆解 - 国麟测评
  • 2026年重型货架厂家怎么选?从台州、成都到中山,这些正规厂商值得关注! - 优质品牌商家
  • ChatGLM2-6B模型拆解:Prefix Decoder架构如何融合双向与单向注意力?
  • 2024广州民办高中测评:零基础择校避坑指南 - 服务品牌热点
  • 2026台州卫生间漏水不用砸砖?微创补漏靠谱方案 - 苏易修缮
  • 2026年好用的视频去水印软件有哪些?视频去水印软件推荐实用教程
  • F28335的I2C时钟配置踩坑实录:从400kHz降到100kHz才稳定的背后
  • AI写论文绝佳选择,4款AI论文写作工具,轻松打造高质量论文!
  • 保姆级教程:用Nav2行为树给你的机器人导航加上“智能大脑”(附完整XML配置)
  • 【Rust】18-宏系统:声明宏、过程宏与代码生成
  • 2026年长春小提琴培训行业观察:教学体系、师资结构与学员成长路径分析 - 优质品牌商家
  • 2026深圳黄金回收便民服务指南,规范门店名录与特色优势全览! - 奢侈品交易观察员
  • 2026 湖州厨卫屋面地下室漏水瓷砖空鼓测评:吉修匠 99.8 分五星榜首 - 吉修匠
  • Windows下可直接运行的模板旋转匹配工具:自动输出XY坐标和旋转角度
  • Windows右键菜单终极清理指南:一键告别臃肿菜单的完整教程
  • Hugging Face Transformers:从模型加载到边缘部署的工业级AI工作流
  • 从《宫娥》到《睡莲》:技术博主如何用图像学方法看懂艺术史里的“密码”?
  • 从汽车级EEPROM选型到开源磨损均衡算法:手把手教你设计高可靠嵌入式存储模块(附避坑指南)
  • 伪Anosov流与双曲3-流形构造技术解析