Rust 基礎からマスターまで — 第9回
スレッド、チャンネル、Mutexで並行性を設定する
本ブログ作成文は、講義を目指して製作されました。 また、作成された文章の情報も間違っている可能性がありますので、ご注意ください。
Rustはデータ競争を生み出すことができる共有アプローチをタイプに制限します。 スレッド、チャンネル、Mutexを使用しても、作業終了とロック範囲は直接設計する必要があります。
スレッドの開始と終了
use std::thread;
let handle = thread::spawn(|| {
load_world_data()
});
let world = handle
.join()
.expect("worker thread panicked");
spawnに渡したクロージャは新しいスレッドで実行されます。 joinはジョブの完了を待ち、panicかどうかを結果に返します。
クロージャが外部値を使用する場合は、スレッドより長く生きる必要があるため、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}");
}
チャネルは、値を共有するのではなく、あるジョブから別のジョブにメッセージを移動します。 送信者がすべて消えた場合、受信者はチャネルが閉じられたことを知ることができる。
ArcとMutex
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は一度に1つの変更アクセスしか許可しません。 ロックを長く保持したり、複数のロックを異なる順序で取得したりすると、パフォーマンスの低下やデッドロックが発生する可能性があります。
並行性はスレッド数を増やすことではありません。 共有状態を減らしてメッセージの境界を設定した後、作業サイズと待ち時間を実際に測定する必要があります。