Rustでは、所有権システムと型チェックにより、多くの並行処理に関するバグがコンパイル時に検出される。この特性は「フェアレス・コンカレンシー(fearless concurrency)」と呼ばれ、開発段階で問題を修正できる点が大きな利点となる。
並行(Concurrent)と並列(Parallel)の違い
並行とは複数のタスクが独立して進行することを指し、必ずしも同時に実行されるわけではない。一方、並列は物理的に同時に実行されることを意味する。ただし、実際の実装では両者が重なり合うことも多い。
Rustの並行処理モデル
- メッセージパッシング:チャネル(
channel)を介してスレッド間でデータを送受信する方式。 - 共有状態:複数のスレッドが同一のメモリ領域にアクセスする方式。Rustでは
MutexやRwLockなどで安全に制御される。 SendとSyncトレイト:これらのトレイトにより、ユーザー定義型も含めてスレッド間での安全なデータ共有が保証される。
シンプルなスレッド使用例
use std::thread;
use std::time::Duration;
fn main() {
let numbers = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
let worker = thread::spawn(move || -> Vec<i32> {
for &n in &numbers {
println!("Worker thread: {}", n);
thread::sleep(Duration::from_millis(50));
}
numbers
});
for i in 0..10 {
println!("Main thread: {}", i);
thread::sleep(Duration::from_millis(20));
}
let result = worker.join().unwrap();
println!("Received from worker: {:?}", result);
}
このコードのポイント:
moveキーワードにより、閉包が所有権を取得し、スレッド間でデータを安全に移動できる。thread::spawnはJoinHandle<T>を返し、join()でスレッドの終了を待ち、結果を取得する。- スレッド関数のシグネチャは
FnOnce() -> TかつSend + 'staticである必要がある。