← SEARCHABLE ARCHIVE
Rust · 2026-08-11

Rust 基礎からマスターまで — 第9回

スレッド、チャンネル、Mutexで並行性を設定する

INTERACTIVE READING MODE →

本ブログ作成文は、講義を目指して製作されました。 また、作成された文章の情報も間違っている可能性がありますので、ご注意ください。

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つの変更アクセスしか許可しません。 ロックを長く保持したり、複数のロックを異なる順序で取得したりすると、パフォーマンスの低下やデッドロックが発生する可能性があります。

並行性はスレッド数を増やすことではありません。 共有状態を減らしてメッセージの境界を設定した後、作業サイズと待ち時間を実際に測定する必要があります。