Rust 的异步
Rust 的异步生态主要围绕 async/.await
语法和 Future
trait 构建。标准库提供了最核心的 trait 和关键字,而具体的运行时(Runtime)则由社区库提供。
关键字 async/await 与 Future Trait
async
/ .await
关键字
async
: 用于标记一个函数、代码块或闭包,将其转换为一个返回 Future
的对象。这个 Future 是惰性的,只有在被轮询(poll)时才会执行。.await
: 用于在 async
函数内部等待另一个 Future
完成。.await
会挂起当前任务,将线程控制权交还给运行时,以便运行其他任务,直到等待的 Future 就绪。
Future
Trait (std::future::Future
)
- 这是异步计算的核心抽象。一个
Future
代表一个可能尚未就绪的值。 - 它有一个
poll
方法,运行时调用它来推动 Future 向前执行。poll
返回 Poll::Ready(T)
表示完成,或 Poll::Pending
表示尚未完成,需要再次被轮询。
核心运行时组件(社区库)
Rust 标准库不提供异步运行时(执行器、调度器、反应器)。你需要选择一个社区提供的运行时。最常见的两个是 tokio
和 async-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);
});
}
|