Rust Async 异步编程(三):使用 Waker 来唤醒任务

Rust异步运行时核心原理:手搓极简Async Runtime实现物理射线检测 异步编程是现代高并发系统的核心技术,其核心机制是通过Future、Executor和Waker的协作实现非阻塞任务调度。Future代表一个可能尚未完成的计算,Executor负责调度和执行这些Future,而Waker则充当任务唤醒的通信枢纽。这种机制的价值在于能够高效利用系统资源,避免线程阻塞,特别适合I/O密集型和高并发场景。在计算密集型领域如物理射线检测中,通用运行时可能带来不必要的开销,因此需要定制化的解决方案。通过实现一个极简的async runtime,可以深入理解任务调度和唤醒机制,掌握Fu 阅读详情

Rust Async 异步编程(三):使用 Waker 来唤醒任务

Rust Async 异步编程(三):使用 Waker 来唤醒任务

异步编程背后到底藏有什么秘密?究竟是哪只幕后之手在操纵这一切?如果你对这些感兴趣,就继续看下去,否则可以直接跳过,因为本章节的内容对于一个 API 工程师并没有太多帮助。

但是如果你希望能深入理解 Rust 的 async/.await 代码是如何工作、理解运行时和性能,甚至未来想要构建自己的 async 运行时或相关工具,那么本章节终究不会辜负于你。

构建一个定时器

对于 Future 来说,第一次被 poll 时无法完成任务是很正常的。但它需要确保在未来一旦准备好时,可以通知执行器再次对其进行 poll 进而继续往下执行,该通知就是通过 Waker 类型完成的。

Waker 提供了一个 wake() 方法可以用于告诉执行器:相关的任务可以被唤醒了,此时执行器就可以对相应的 Future 再次进行 poll 操作。

下面一起来实现一个简单的定时器 Future。为了让例子尽量简单,当计时器创建时,我们会启动一个线程接着让该线程进入睡眠,等睡眠结束后再通知给 Future。

注意本例子还会在后面继续使用,因此我们重新创建一个工程来演示:使用 cargo new --lib timer_future 来创建一个新工程,在 lib 包的根路径 src/lib.rs 中添加以下内容:

use std::{
    future::Future,
    pin::Pin,
    sync::{Arc, Mutex},
    task::{Context, Poll, Waker},
    thread,
    time::Duration,
};

继续来实现 Future 定时器,之前提到:新建线程在睡眠结束后会需要将状态同步给定时器 Future,由于是多线程环境,我们需要使用 Arc<Mutex<T>> 来作为一个共享状态,用于在新线程和 Future 定时器间共享。

pub struct TimerFuture {
    shared_state: Arc<Mutex<SharedState>>,
}

/// 在 Future 和等待的线程间共享状态
struct SharedState {
    /// 定时(睡眠)是否结束
    completed: bool,

    /// 当睡眠结束后,线程可以用 waker 通知 TimerFuture 来唤醒任务
    waker: Option<Waker>,
}

下面给出 Future 的具体实现:

impl Future for TimerFuture {
    type Output = ();
    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
        // 通过检查共享状态,来确定定时器是否已经完成
        let mut shared_state = self.shared_state.lock().unwrap();
        if shared_state.completed {
            Poll::Ready(())
        } else {
            // 设置 waker,这样新线程在睡眠(计时)结束后可以唤醒当前的任务,接着再次对 Future 进行 poll 操作,
            // 
            // 下面的 clone 每次被 pol 时都会发生一次,实际上,应该是只 clone 一次更加合理。
            // 选择每次都 clone 的原因是:TimerFuture 可以在执行器的不同任务间移动,如果只克隆一次,那么获取到的 waker 可能已经被篡改并指向了其它任务,最终导致执行器运行了错误的任务。
            shared_state.waker = Some(cx.waker().clone());
            Poll::Pending
        }
    }
}

代码很简单,只要新线程设置了 shared_state.completed = true,那任务就能顺利结束。如果没有设置,会为当前的任务克隆一份 Waker,这样新线程就可以使用它来唤醒当前的任务。

最后,再来创建一个 API 用于构建定时器和启动计时线程:

impl TimerFuture {
    /// 创建一个新的 TimerFuture,在指定的时间结束后,该 Future 可以完成
    pub fn new(duration: Duration) -> Self {
        let shared_state = Arc::new(Mutex::new(SharedState {
            completed: false,
            waker: None,
        }));

        // 创建新线程
        let thread_shared_state = shared_state.clone();
        thread::spawn(move || {
            // 睡眠指定时间实现计时功能
            thread::sleep(duration);
            let mut shared_state = thread_shared_state.lock().unwrap();
            // 通知执行器定时器已经完成,可以继续 poll 对应的 Future 了
            shared_state.completed = true;
            if let Some(waker) = shared_state.waker.take() {
                waker.wake()
            }
        });

        TimerFuture { shared_state }
    }
}

至此,一个简单的定时器 Future 就已创建成功,那么该如何使用它呢?相信部分爱动脑筋的读者已经猜到了:我们需要创建一个执行器,才能让程序动起来。

参考

  1. https://github.com/rustcn-org/async-book
  2. https://www.bilibili.com/video/BV1Ki4y1C7gj
一个用 Rust 编写的简单 CLI 番茄钟定时器。 番茄钟一个用 Rust 编写的简单 CLI 番茄钟定时器。基于番茄工作法。适用于任何支持桌面通知的平台。例子pomodoro 25 4以 25 分钟的工作间隔和 4 分钟的休息间隔开始一个番茄钟会话。 立即下载

相关推荐

timer.rs:Rust计时器的简单实现

计时器 在Rust中以及针对Rust的Timer的简单实现。 例子 extern crate timer; extern crate chrono; use std :: sync :: mpsc :: channel; let timer = timer :: Timer :: new (); let (tx, rx) = channel (); let _guard = timer. schedule_with_delay (chrono :: Duration :: seconds ( 3 ), move || { tx. send (()). unwrap (); }); rx. recv (). unwrap (); println! ( "This code has been executed after 3 seconds" );

Let‘s Go Rust 系列之定时器 Ticker Timer

前言 在实际项目开发中,经常会有定时任务的功能开发需求,定时任务主要分为两种, 1,在固定的时刻执行某个任务,也就是 Timer 2,基于固定的时间间隔,周期的执行某个任务,也就是Ticker ​ 很多基于时间的调度任务框架都离不开这两种类型。 本文将会分别介绍在Golang和Rust语言中这两种定时器类型以及它们的使用方法。 Golang Golang的标准库 time 中就包含了 Ticker 和 Timer 这两种定时器类型,在package中添加引用就可,如下: ​ import ( "ti

Deepexi_Date的博客 2823

异步计时器:Rust异步故事的计时器功能

异步计时器 Rust异步故事的计时器功能 最低Rust版本:1.36 准确性 不依赖异步事件循环的常规计时器通常与tokio用户空间计时器处于同等水平。 如果这不适合您,则应启用基于事件循环的计时器,在大多数情况下,该计时器将为您提供在UNIX平台上可能最准确的计时器(请参阅功能)。 特征 tokio1使用tokio启用基于事件循环的计时器,从而在unix平台上提供更高分辨率的计时器。 c_wrapper使用C填充程序创建到平台API的绑定,该绑定可能比libc更可靠。 std启用std类型的使用(例如Error) stream -启用Stream实施Interval 例子 定时的 async fn job () { } async fn do_job () { let work = unsafe { async_timer :: Timed :: plat

rust高级 异步编程 一 future

OS线程, 它最简单,也无需改变任何编程模型(业务/代码逻辑),因此非常适合作为语言的原生并发模型,我们在多线程章节也提到过,Rust 就选择了原生支持线程级的并发编程。但是,这种模型也有缺点,例如线程间的同步将变得更加困难,线程间的上下文切换损耗较大。使用线程池在一定程度上可以提升性能,但是对于 IO 密集的场景来说,线程池还是不够。事件驱动(Event driven),如果说事件驱动常常跟回调( Callback )一起使用,相信大家就恍然大悟了。

个人博客,记录了本人学习的各种有趣的技术。 3524

Unity游戏接入穿山甲广告SDK全攻略:从零到上线的避坑指南

本文为Unity开发者提供了接入穿山甲广告SDK的完整实战指南。详细解析了从账号注册、应用创建到Unity插件集成、安卓与iOS平台打包配置的全流程,并重点分享了广告加载失败、展示异常等常见问题的排查与解决方案,帮助开发者高效实现游戏广告变现。

weixin_29015899的博客 536

金蝶个版本下载地址,记得保存收藏。

专业版 V10.0 http://downloads.cmcloud.cn/kis/kis_pro/10.0/kiszybV10sp1.rar V11.0 http://downloads.cmcloud.cn/kis/kis_pro/11.0/KISV11Setup.rar V12.0 http://dow...

饺子的博客 2512

Rust 异步编程:Tokio 定时器实现机制的深度解析

Tokio的定时器实现展现了系统编程的精妙设计:通过分层轮盘、最小堆和与运行时的深度集成,实现了高效、可靠的定时机制。理解这些底层设计,我们能够:合理选择定时器API,避免性能陷阱优化包含大量定时任务的系统诊断与解决定时相关的问题掌握Tokio定时器,就掌握了异步系统设计的重要一环!🚀。

2501_93809844的博客 392

Python自动化批量识别化学分子结构——从图片到SMILES/SDF的实战指南

本文提供了使用Python自动化批量识别化学分子结构图片的实战指南。详细对比了基于Molvec API的在线快速方案与本地部署OSRA工具的两种路径,包含完整的代码示例、环境配置及优化技巧,帮助化学研究者高效地将图片批量转换为SMILES或SDF格式,显著提升数据处理效率。

apple5的专栏 947

rust定时任务

在 Rust 中实现定时任务,社区提供了丰富的库,可以根据你的具体需求(是简单地在程序内部调度,还是需要持久化、分布式执行)来选择不同的方案。下面我将这些方案分为两大类,方便你对比和选择。

leijmdas的专栏 355

CryoEM - 使用 ChimeraX 工具 操作 冷冻电镜的 MRC 密度图(Density Map) 教程

由冷冻电镜 CryoSparc 软件所生成的 Volume,需要观察其内部结构,建议使用 ChimeraX 进行操作。

AGI 4963

高通8155源码下载与Android源码编译

一.下载代码 高通下载源码位置: Qualcomm CreatePoint 注册账号,然后登入 可以先选择edit -> infotainment -> sa8155 -> favorites, 点击View TOC就可以过滤出sa8155所有的信息目录.如下图 拉取代码链接在ChipCode中,点击进去可以看到所有的基线版本,选择你需要下载的版本点进去,如sa8155p-la-1-0_ap_standard_oem,把高通专有代码和开源代码都下载到本机. 1..

Johnny2004的专栏 7675

Rust Waker 与唤醒机制:异步任务的 “唤醒桥梁” 与底层逻辑解析

Rust 的 Waker 封装在std::task::Waker中,它并非具体的实现,而是一套 “唤醒能力” 的抽象 Trait。其设计意图是 “解耦任务与事件源”—— 任务无需关心事件源的具体类型(如 I/O、定时器),只需提供 Waker 作为 “唤醒回调”;事件源无需关心任务的具体逻辑,只需在事件完成时调用 Waker 的唤醒方法。std::task::Waker的核心方法简化后如下(聚焦关键逻辑):// 内部封装:指向唤醒逻辑的Trait Object(轻量级间接层)

2501_94047848的博客 782

华为OD机考双机位C卷 - 采购订单 (Java & Python& JS & C/C++ & GO )

华为OD机考双机位C卷 - 采购订单 。提供Java、C++、Python、Go、JavaScript源码实现,并提供完整思路讲解,以及在线OJ模拟做题。

算法大师! 427

Rust 异步运行时的设计与实现:从 Future 状态机到 Waker 唤醒机制的完整解析

Rust 的异步运行时通过编译期状态机生成 + 轻量级 Waker 唤醒机制,实现了接近零运行时的异步抽象。tokio 的调度模型是协作式的——每个.await都是显式 yield 点,Runtime 通过工作窃取实现多核负载均衡。Waker 作为 Future 与 I/O Reactor 的唯一通信桥梁,其轻量设计(2 个 usize)是整个唤醒链路的性能基础。

iymei4986533030的博客 4581

富芮坤fr8008gp 240X280 lvgl项目启动

fr8008gp_240X280_lvgl项目启动

cheng___yi的博客 1758

VisionPro - 基础 - 模板匹配技术-Search/PMAlign/PatMax(6)-纹理屏蔽和重叠匹配

Note:对已经有了,1已经训练好的模板,2一组使能的自由度,3一个待测的实时图片,PatMax 就能模板匹配的给出变化的最佳描述。对一些综合的模板,这三个输入值往往是一起影响最后的变换结果信息。例如,如果我们训练了一个圆形的模板,然后搜索一个角度自由度包括一个圆,那么将会有无限个可能的角度满足要求。这些组合的模板匹配,被官方名为:退化系统,a degenerate system的结果被叫做a degenerate result 退化结果4.2 退化系统例子。

山云的专栏 1534

Rust异步编程实战:构建高性能网络应用

本文介绍了Rust异步编程的核心概念与实践方法。首先对比了同步与异步编程的区别,阐述了异步编程在高并发场景下的优势。随后详细讲解了Rust异步编程的演进历程,重点介绍了Future、Poll和Waker三个核心概念。文章通过代码示例展示了async/await语法的使用方式,包括异步函数的定义和执行流程。最后深入讲解了Tokio异步运行时的架构、安装配置方法,并提供了TCP服务器/客户端的实现示例,帮助开发者掌握Rust高性能网络应用的构建方法。

编程世界如山海,探索不止。 9679

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

揭秘Rust异步运行时:从Future到Waker的底层机制全解析

掌握rust异步编程核心机制,深入解析Future、Waker与运行时协作原理。涵盖异步任务调度、轮询触发及零成本抽象优势,适用于高性能网络服务与并发场景。底层逻辑全揭秘,值得收藏。

PixelGlow的博客 607

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

Rust异步编程深度解析:从Future到Runtime

异步编程已经成为现代高性能应用开发的核心能力。无论是需要同时处理成千上万个连接的 Web 服务器,还是执行大量并发 I/O 操作的数据处理系统,异步模型都能显著提升系统的吞吐量与资源利用率。与 Go 语言的 goroutine 或 JavaScript 的 Promise 不同,Rust 的异步模型建立在零成本抽象的原则之上,通过编译期优化实现了既安全又高效的异步执行。 然而,这种设计也带来了一定的学习曲线 —— async/await 关键字背后隐藏着复杂的状态机转换,Future trait 的工作机制

Allen- 5665

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

Rust 异步运行时深度剖析:从 Executor 调度到 Waker 机制

Waker 是连接 Future 和 Executor 的关键。当异步操作(如 I/O)完成时,底层会调用wake()通知执行器重新调度任务。// 将任务重新加入队列深度理解wake()消费Arc<Self>只借用,后者更高效在多线程场景下,需要确保task_queue的线程安全Waker 可以被克隆多次,每次克隆都增加引用计数Future 的惰性本质:不主动执行,必须被 pollExecutor 的职责:调度、轮询、响应唤醒Waker 的艺术:连接异步操作和执行器的桥梁。

2301_76618579的博客 1990

Rust 异步运行时原理:从 Future 到 Waker 再到 Executor

回调 (Callbacks):(Node.js 早期) 逻辑分散,难以跟踪,导致“回调地狱”。协程 (Goroutines):(Go 语言) M:N 调度,有栈协程,易于使用但内存开销大(~2KB 起步),且依赖运行时。:(JavaScript) 链式调用,解决了回调地狱,但前仍显繁琐。:无栈协程,Future只是一个状态机,内存开销极小小(几十字节),不依赖特定运行时。Taskasyncait:编译为实现了FutureTrait 的状态机。:异步的核心,Executor 通过轮询来驱动。

LZL_SQ的博客 510

Future 与轮询:Async Rust 并发模型的底层机制与生产实践

Async Rust 的核心设计是 Future 状态机 + Waker 唤醒机制,通过编译期变换将 async/await 语法转化为零分配的状态机轮询。本文从 Future 的 poll 语义出发,展示了并发限流器、优雅关闭管理器和异步管道三个生产级模式。落地路线建议:第一步,使用处理独立异步任务,通过JoinSet管理任务生命周期;第二步,引入Semaphore实现并发限流,防止下游服务过载;第三步,使用broadcastchannel 实现优雅关闭,确保 SIGTERM 信号后所有任务完成清理;

no1coder的博客 1070

Rust 异步编程深度解析:从 Future 到运行时

本文深入解析Rust异步编程的底层机制,从Future trait的设计实现到运行时的工作流程。Rust通过惰性执行的Future状态机、Pin机制解决自引用问题,实现了零成本抽象的并发处理。文章详细剖析了async/await语法糖背后的编译器转换、Waker调度机制,以及Tokio运行时的任务调度和I/O反应器实现。同时提供了性能优化实践和常见陷阱规避策略,帮助开发者充分利用Rust异步编程的优势,在保证内存安全的前提下实现高性能并发。

踏雨歌青春,诗酒趁年华 6123

Rust async/await 模式:从 Future 到 Tokio,异步编程的正确打开方式

Future 是惰性的、.await 是让出点、阻塞操作必须隔离。理解惰性:async fn 调用不执行代码,必须 .await 或 spawn。这是与 Go/JS 异步最大的区别。选择运行时:新项目用 Tokio,生态最成熟。理解 Tokio 的工作窃取调度和多线程线程池。避免阻塞:async 任务中不做 CPU 密集计算和阻塞 IO,用 spawn_blocking 隔离。掌握组合子:join!并发等待全部、select!竞争等待最快、timeout 限制时间,覆盖 90% 的并发模式。

no1coder的博客 4543

Rust Async Easy

async await join

SStringss的博客 523

Rust 异步编程详解:`async/await`、`Future` 与 `Pin/Unpin` 深度解析

本文深入解析Rust异步编程的核心机制,探讨async/await如何被编译为状态机,FutureTrait如何通过poll方法实现任务驱动,以及Pin/Unpin如何解决自引用结构体的内存安全问题。文章指出:1) async fn生成惰性Future,编译器将其转换为带暂停点的状态机;2) Future::poll配合Waker实现非阻塞唤醒;3) Pin<T>禁止自引用结构体移动,确保内存安全;4) Unpin标记安全可移动类型。这些机制的协同作用使Rust能高效安全地处理高并发任务。

AtomicVerse的博客 865
上一篇: Rust Async 异步编程(二):Future trait
下一篇: Rust Async 异步编程(四):Executor
UestcXiye
博客等级 码龄8年 9031粉丝 1306原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

UestcXiye

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值