Rust - 用异步替代线程实现并发

关键概念对比

功能 多线程方式 异步方式
创建并发单元 thread::spawn() trpl::spawn_task()
延时等待 thread::sleep() (阻塞线程) trpl::sleep().await (非阻塞)
等待结束 join() (阻塞线程) .await (让出控制权)
并发单位 操作系统线程 (重量级) Future (轻量级状态机)

三种异步模式详解

1️⃣ 基础任务生成(示例17-6)

rust 复制代码
# extern crate trpl; // required for mdbook test 
# use std::time::Duration; 
fn main() { 
    trpl::run(async { 
        trpl::spawn_task(async { 
            for i in 1..10 { 
                println!("hi number {i} from the first task!"); 
                trpl::sleep(Duration::from_millis(500)).await; 
            } 
        }); 
        
        for i in 1..5 { 
            println!("hi number {i} from the second task!"); 
            trpl::sleep(Duration::from_millis(500)).await; 
        } 
   }); 
}

特点

  • 主任务结束时自动终止子任务
  • 类似守护线程(daemon thread)
  • 输出顺序随机(取决于运行时调度)

2️⃣ 使用任务句柄等待

rust 复制代码
# extern crate trpl; // required for mdbook test 
# 
# use std::time::Duration; 
# 
# fn main() { 
#    trpl::run(async { 
        let handle = trpl::spawn_task(async { 
            for i in 1..10 { 
                println!("hi number {i} from the first task!");
                trpl::sleep(Duration::from_millis(500)).await; 
            } 
        }); 
        
        for i in 1..5 { 
            println!("hi number {i} from the second task!");
            trpl::sleep(Duration::from_millis(500)).await; 
        } 
        handle.await.unwrap(); 
#    }); 
#}

核心改进

  • 通过 handle.await 确保子任务完整执行
  • 类似线程的 join(),但非阻塞
  • 输出顺序依然随机

3️⃣ 使用join组合Future(示例17-8)

rust 复制代码
# extern crate trpl; // required for mdbook test 
# 
# use std::time::Duration; 
# 
# fn main() { 
#     trpl::run(async { 
           let fut1 = async { 
               for i in 1..10 { 
                   println!("hi number {i} from the first task!"); 
                   trpl::sleep(Duration::from_millis(500)).await; 
               } 
           }; 
           
           let fut2 = async { 
               for i in 1..5 { 
                   println!("hi number {i} from the second task!"); 
                   trpl::sleep(Duration::from_millis(500)).await; 
               } 
           };
           trpl::join(fut1, fut2).await; 
#     }); 
#}

革命性变化

  • 不需要生成任务,直接操作 Future 对象
  • 运行时公平轮询(round-robin)
  • 输出顺序固定(交替执行)
text 复制代码
hi number 1 from the first task!  // fut1
hi number 1 from the second task! // fut2
hi number 2 from the first task!  // fut1
...

为什么顺序固定?关键机制

  1. 公平调度器

    • trpl::join 内部以固定频率轮询每个 Future
    • 每次只推进少量执行(到下一个 .await 点)
  2. 协作式让步

    rust 复制代码
    // 每次遇到 .await 都会让出控制权
    trpl::sleep(...).await; // ↑ 让出点
  3. 执行流程

    • 轮询 fut1 → 执行到第一个 sleep().await → 暂停
    • 轮询 fut2 → 执行到第一个 sleep().await → 暂停
    • 重复直到两者完成

与线程的本质区别

特性 线程模型 异步模型
内存开销 MB级(线程栈) KB级(状态机)
切换代价 高(内核切换) 极低(用户态切换)
调度单位 整个线程 单个 .await 分段
控制粒度 粗(操作系统控制) 细(程序员可控)

实践建议

  1. 何时用异步

    • I/O密集型任务(网络请求/文件操作)
    • 高并发服务(如Web服务器)
    • 需要数千以上"并发单元"的场景
  2. 何时用线程

    • CPU密集型计算
    • 阻塞型操作(如复杂计算)
    • 需要利用多核并行(非并发)
  3. 混合使用

    rust 复制代码
    // CPU密集型任务放在专用线程
    tokio::task::spawn_blocking(|| heavy_computation());

真实世界映射

示例中的伪API 实际生产级对应
trpl::run #[tokio::main]
trpl::sleep tokio::time::sleep()
trpl::join tokio::join!
spawn_task tokio::spawn()
相关推荐
好家伙VCC14 小时前
**发散创新:基于Rust的轻量级权限管理库设计与开源许可证实践**在现代分布式系统中,**权限控制(RBAC
java·开发语言·python·rust·开源
@atweiwei14 小时前
用 Rust 构建agent的 LLM 应用的高性能框架
开发语言·后端·rust·langchain·eclipse·llm·agent
skilllite作者14 小时前
Spec + Task 作为「开发协议层」:Rust 大模型辅助的标准化、harness 化与可回滚
开发语言·人工智能·后端·安全·架构·rust·rust沙箱
zsqw12317 小时前
以 Rust 为例,聊聊线性类型,以及整个类型系统
rust·编译器
Rust研习社18 小时前
Rust Tracing 实战指南:从基础用法到生产级落地
rust
分布式存储与RustFS18 小时前
MinIO迎来“恶龙”?RustFS这款开源存储简直“不讲武德”
架构·rust·开源·对象存储·minio·企业存储·rustfs
数据知道1 天前
claw-code 源码分析:从 TypeScript 心智到 Python/Rust——跨栈移植时类型、边界与错误模型怎么对齐?
python·ai·rust·typescript·claude code·claw code
Rust研习社2 天前
深入浅出 Rust 迭代器:从基础用法到性能优化
rust
@atweiwei2 天前
langchainrust:Rust 版 LangChain 框架(LLM+Agent+RAG)
开发语言·rust·langchain·agent·向量数据库·rag