blog.dopana

Back

Rust中級シリーズの第15回。並行プログラミング(Concurrency)は、データ競合やデッドロック、メモリ破壊などが発生しやすく、伝統的に難易度が高い領域でした。

Rustはこれを Fearless Concurrency(恐れなき並行処理) という概念で解決します。所有権と型システムにより、並行処理におけるメモリ安全性の欠陥が実行時エラーではなく、コンパイル時エラーとして検出されます。

graph TD
    A["Rustの恐れなき並行処理"] --> B["スレッド生成<br/>std::thread::spawn"]
    A --> C["メッセージパッシング<br/>Channels (mpsc)"]
    A --> D["状態の共有<br/>Arc<T> + Mutex<T>"]
    A --> E["安全性の拡張<br/>Send & Sync トレイト"]

10歳でもわかる説明(ELI5):大忙しのレストランの厨房#

レストランの厨房をイメージしてください:

  1. シングルスレッド:1人のシェフが野菜切りから調理、皿洗いまで全て行います。安全ですがスピードに限界があります。
  2. 安全性のないマルチスレッド(C/C++):5人のシェフが何のルールもなく同じまな板やフライパンに手を伸ばし、誤って手を切ったり具材が混ざったりします(データ競合・メモリ破壊)。
  3. Rustの恐れなき並行処理:シェフごとに担当ブースが割り振られ(所有権)、注文伝票は専用レーン(チャンネル)で受け渡します。共有器具を使うときは鍵付きロッカー(Arc + Mutex)で管理されます。料理長(コンパイラ)が開店前に全手順を厳格にチェックします!

1. スレッドによるコードの並行実行#

Rustでは thread::spawn を使ってネイティブOSスレッドを生成します:

move クロージャによる所有権の移動#

スレッド内で外側のスコープのデータを使用する場合、move キーワードで所有権をスレッドに移動(transfer)させます:

src/main.rs
use std::thread;

fn main() {
    let v = vec![1, 2, 3];

    let handle = thread::spawn(move || {
        println!("スレッド内のベクタ: {v:?}");
    });

    handle.join().unwrap();
}
rust

2. メッセージパッシング:チャンネル (mpsc)#

Go言語で有名な格言「メモリを共有して通信するのではなく、通信することでメモリを共有せよ」は、Rustでも強く推奨されています。

標準ライブラリの mpsc(multiple producer, single consumer:複数の送信者、単一の受信者)を利用します:

3. 状態の共有:Arc<T>Mutex<T>#

複数のスレッド間で同じデータを共有・変更する必要がある場合:

  • Mutex<T>(相互排他):同時に1つのスレッドのみが lock() を取得してデータにアクセスできるよう保護します。
  • Arc<T>(アトミック参照カウント):複数のスレッド間で安全に所有権を共有できるスマートポインタです。

[!NOTE] Rc<T> は参照カウントの更新がアトミックではないため、スレッドセーフではありません。スレッド間をまたぐデータ共有には、必ず Arc<T> を使用してください。

4. 安全性を支える2つのトレイト:SendSync#

Rustの並行処理モデルは言語のコアに固定されているのではなく、以下の2つの自動トレイトに基づいています:

  1. Send:スレッド間で型の所有権を転送できることを示します。
  2. Sync:複数のスレッドから型への参照(&T)を同時にアクセスしても安全であることを示します(T: Sync&T: Send と同等)。

Rustのほぼすべての基本型は自動的に Send かつ Sync です。スレッドセーフでない型(Rc<T> など)をスレッド間で共有しようとすると、コンパイラが即座にエラーを出して不正なプログラムの生成を防ぎます。

まとめ#

  • thread::spawnmove クロージャで安全なスレッド生成とデータ移動が行えます。
  • mpsc::channel により、所有権モデルを活かした安全なメッセージ通信が可能です。
  • Arc<Mutex<T>> はマルチスレッド間で可変データを安全に共有するための標準パターンです。
  • SendSync トレイトがコンパイル時のデータ競合防止を支えています。

参考文献#