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 一次只允許一項變更存取。 長時間持有鎖或以不同的順序獲取多個鎖可能會導致性能不佳和死鎖。
並發並不是增加線程數量。 減少共享狀態並定義訊息邊界後,您需要實際測量操作的大小和延遲。