rust-concurrency - 課題

概要

Rustの並行処理機能を学び、スレッドセーフなプログラムを実装する課題です。

マンダトリーパート

必須要件

  • スレッド間のデータ共有
- Arc> を使用した共有状態 - 複数スレッドからの安全なアクセス

  • メッセージパッシング
- チャネルを使用したスレッド間通信 - 複数プロデューサー・単一コンシューマー

  • 並列処理ユーティリティ
- スレッドプール - 並列マップ処理

インターフェース

use std::sync::{Arc, Mutex, mpsc};
use std::thread;

/// スレッドセーフなカウンター
pub struct Counter {
    count: Arc<Mutex<u64>>,
}

impl Counter {
    pub fn new() -> Self;
    pub fn increment(&self);
    pub fn get(&self) -> u64;
}

/// チャネルベースのワーカー
pub fn spawn_workers<T, F, R>(
    items: Vec<T>,
    worker_count: usize,
    process: F,
) -> Vec<R>
where
    T: Send + 'static,
    R: Send + 'static,
    F: Fn(T) -> R + Send + Clone + 'static;

/// スレッドプール
pub struct ThreadPool {
    workers: Vec<Worker>,
    sender: mpsc::Sender<Job>,
}

impl ThreadPool {
    pub fn new(size: usize) -> Self;
    pub fn execute<F>(&self, f: F)
    where
        F: FnOnce() + Send + 'static;
}

/// 並列イテレータ風の処理
pub fn parallel_map<T, U, F>(items: Vec<T>, f: F) -> Vec<U>
where
    T: Send + 'static,
    U: Send + 'static,
    F: Fn(T) -> U + Send + Sync + 'static;

使用例

// カウンター
let counter = Counter::new();
let handles: Vec<_> = (0..10).map(|_| {
    let c = counter.clone();
    thread::spawn(move || {
        for _ in 0..100 {
            c.increment();
        }
    })
}).collect();

for h in handles { h.join().unwrap(); }
assert_eq!(counter.get(), 1000);

// スレッドプール
let pool = ThreadPool::new(4);
pool.execute(|| println!("Task 1"));
pool.execute(|| println!("Task 2"));

ボーナスパート

ボーナス1: バリア同期

  • 複数スレッドの同期ポイント

ボーナス2: 読み書きロック

  • RwLock を使用した最適化

ボーナス3: アトミック操作

  • ロックフリーカウンター
  • 提出要件

  • src/counter.rs - スレッドセーフカウンター
  • src/channel.rs - チャネル処理
  • src/pool.rs - スレッドプール
  • Cargo.toml
  • 制限事項

  • unsafe は使用不可
  • 外部クレート(rayon等)は使用不可