并发与异步
Rust 的类型系统让并发与异步在编译期就暴露出大量错误,常见模式可分为三类:线程、共享状态与 async 任务。
线程与 move 闭包
std::thread::spawn 启动新线程,要求闭包为 'static,因此需要 move 把捕获变量移入。新线程返回值通过 JoinHandle 的 .join() 拿回。
use std::thread;
let h = thread::spawn(move || println!("hi"));
h.join().unwrap();
mpsc 通道
多生产者单消费者(std::sync::mpsc::channel)用于在线程间传递消息。tx.send(v) 发送,rx.recv() 阻塞接收,语义直观且无需锁。
let (tx, rx) = std::sync::mpsc::channel();
tx.send(1).unwrap();
let v = rx.recv().unwrap();
共享状态:Arc<Mutex<T>>
若线程间需要共享同一份数据,常见组合是 Arc<Mutex<T>>:Arc 提供线程安全的引用计数,Mutex 互斥访问内部值。lock() 返回守卫,作用域结束自动解锁。
async/await 基础
async fn 返回实现了 Future 的类型。await 挂起当前任务直到结果就绪。Future 是惰性的,必须由运行时驱动才执行。
async fn fetch() -> u32 { 42 }
let v = fetch().await;
tokio::main
标准库不提供执行器,社区最常用的是 tokio。通过 #[tokio::main] 宏将 main 改为异步入口,内部启动多线程运行时,直接 await 异步任务即可。
#[tokio::main]
async fn main() {
let v = fetch().await;
println!("{v}");
}
合理选用线程、通道与 async 任务,既能榨干多核性能,又能保持代码的清晰与安全。