从 Rust 基础到掌握 — 第 9 集
配置线程、通道和互斥体的并发性
该博客上撰写的文章是出于教学目的而创建的。 另外,文章中的信息可能不正确,请谨慎。
Rust 限制对类型的共享访问,这可能会造成数据竞争。 即使您使用线程、通道或互斥体,您也必须自己设计任务终止和锁定范围。
开始和结束线程
use std::thread;
let handle = thread::spawn(|| {
load_world_data()
});
let world = handle
.join()
.expect("worker thread panicked");
传递给spawn的闭包在新线程中执行。 join 等待任务完成并返回,无论结果是否出现恐慌。
如果闭包使用外部值,它必须比线程更长寿,因此所有权通常会转移到 move。
向频道发送消息
use std::sync::mpsc;
let (sender, receiver) = mpsc::channel();
thread::spawn(move || {
sender.send(String::from("Loaded")).unwrap();
});
if let Ok(message) = receiver.recv() {
println!("{message}");
}
渠道将消息从一项任务转移到另一项任务,而不是共享价值。 当所有发送者消失时,接收者就知道通道已关闭。
弧线和互斥体
use std::sync::{Arc, Mutex};
let score = Arc::new(Mutex::new(0));
let worker_score = Arc::clone(&score);
let handle = thread::spawn(move || {
let mut value = worker_score.lock().unwrap();
*value += 10;
});
handle.join().unwrap();
Arc 在线程之间共享所有权,而 Mutex 一次只允许一项更改访问。 长时间持有锁或以不同的顺序获取多个锁可能会导致性能不佳和死锁。
并发并不是增加线程数量。 减少共享状态并定义消息边界后,您需要实际测量操作的大小和延迟。