Rust 的异步

Rust 的异步

Rust 的异步生态主要围绕 async/.await 语法和 Future trait 构建。标准库提供了最核心的 trait 和关键字,而具体的运行时(Runtime)则由社区库提供。

关键字 async/await 与 Future Trait

  1. async / .await 关键字
  • async: 用于标记一个函数、代码块或闭包,将其转换为一个返回 Future 的对象。这个 Future 是惰性的,只有在被轮询(poll)时才会执行。
  • .await: 用于在 async 函数内部等待另一个 Future 完成。.await 会挂起当前任务,将线程控制权交还给运行时,以便运行其他任务,直到等待的 Future 就绪。
  1. Future Trait (std::future::Future)
  • 这是异步计算的核心抽象。一个 Future 代表一个可能尚未就绪的值。
  • 它有一个 poll 方法,运行时调用它来推动 Future 向前执行。poll 返回 Poll::Ready(T) 表示完成,或 Poll::Pending 表示尚未完成,需要再次被轮询。

核心运行时组件(社区库)

Rust 标准库提供异步运行时(执行器、调度器、反应器)。你需要选择一个社区提供的运行时。最常见的两个是 tokioasync-std

核心组件:

  • 执行器 (Executor): 负责调度和执行 Future(任务)。
  • 反应器 (Reactor): 负责与操作系统交互,订阅和响应 I/O 事件(如 TCP 套接字可读、可写)。
  • 定时器 (Timer): 提供异步的睡眠(sleep)和间隔计时功能。

实现过 C++ 的协程应该不难理解上面的三个东西。

takio

常用模块 (tokio crate):

  • tokio::net: 异步的 TCP、UDP、Unix 域套接字。
  • tokio::fs: 异步的文件系统操作。
  • tokio::sync: 异步的同步原语,如 Mutex, RwLock, mpsc (通道), oneshot 等。非常重要,用于在异步任务间安全地共享状态。
  • tokio::time: 提供 sleep, interval, timeout 等功能。
  • tokio::spawn: 用于生成新的异步任务(类似于线程)。
  • tokio::main: 属性宏,用于标记异步的 main 函数,并启动 Tokio 运行时。

For example:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
// 1. 使用 `async fn` 定义一个异步函数
// 它返回一个 `Future<Output = String>`,而不是直接的 String
async fn say_hello() -> String {
    // 这个函数体不会立即执行
    "Hello from an async function!".to_string()
}

// 2. 普通的同步函数
fn say_hi() -> String {
    "Hi from a sync function!".to_string()
}

#[tokio::main] // 这是必需的!它启动了异步运行时
async fn main() {
    // 调用同步函数:立即执行并得到结果
    let hi = say_hi();
    println!("{}", hi); // 输出: Hi from a sync function!

    // 调用异步函数:不会立即执行,只是得到了一个 Future 对象
    let future_hello = say_hello();

    // 3. 使用 `.await` 来等待这个 Future 完成并获取结果
    // 执行流会在这里挂起,直到 say_hello() 的 Future 完成
    let hello = future_hello.await;
    println!("{}", hello); // 输出: Hello from an async function!

    // 更常见的写法是链式调用
    let hello_again = say_hello().await;
    println!("{}", hello_again);
}

Async-std

目标是让异步代码的感觉和标准库一样自然,API 设计与 std 模块高度一致。

For example:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
use async_std::task;

// 1. 使用 `async fn` 定义一个异步函数
// 它返回一个 `Future<Output = String>`,而不是直接的 String
async fn say_hello() -> String {
    // 这个函数体不会立即执行
    "Hello from an async function!".to_string()
}

// 2. 普通的同步函数
fn say_hi() -> String {
    "Hi from a sync function!".to_string()
}

fn main() {
    // async-std 的运行时启动方式
    task::block_on(async {
        // 调用同步函数:立即执行并得到结果
        let hi = say_hi();
        println!("{}", hi); // 输出: Hi from a sync function!

        // 调用异步函数:不会立即执行,只是得到了一个 Future 对象
        let future_hello = say_hello();

        // 3. 使用 `.await` 来等待这个 Future 完成并获取结果
        // 执行流会在这里挂起,直到 say_hello() 的 Future 完成
        let hello = future_hello.await;
        println!("{}", hello); // 输出: Hello from an async function!

        // 更常见的写法是链式调用
        let hello_again = say_hello().await;
        println!("{}", hello_again);
    });
}
0%