Mutex

    Mutex<T>は、共通リソースが複数のスレッド間で競合などが起きないようにしてくれます。::lockを実行することでMutexGuard<T>を取得できます。Tは安全に触りたい値のことで、MutextGuardDerefを持ってることから楽に触る事ができます。

    すべてのスレッドの処理が終わった後、再度Tを取得したい場合はメインスレッドで再度::lockし、MutexGuardに変換してから取得できます。

    use std::sync::{Arc, Mutex};
    use std::thread;
    
    let values: Arc<Mutex<Vec<i32>>> = Arc::new(Mutex::new(Vec::new()));
    
    for i in 0..10 {
      let values = values.clone();
    
      thread::spawn(move || {
        let mut lock = values.lock().unwrap();
        lock.push(i);
      })
      .join()
      .unwrap();
    }
    
    let values = values.lock().unwrap();
    
    assert_eq!(*values, vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
    

    あるスレッドのMutexGuardがスコープを抜けるまで他スレッドでは値を取得できない状態が続きます。なので以下のように書き換えると2つめの"foo"が出るまでに1秒の遅れが生まれます。

    use std::sync::{Arc, Mutex};
    use std::thread;
    use std::time::Duration;
    
    let values: Arc<Mutex<Vec<i32>>> = Arc::new(Mutex::new(Vec::new()));
    
    for i in 0..10 {
      let values = values.clone();
    
      thread::spawn(move || {
        let mut lock = values.lock().unwrap();
    
        println!("foo");
    
        lock.push(i);
    
        if i == 0 {
          thread::sleep(Duration::from_secs(1));
        }
      })
      .join()
      .unwrap();
    }
    
    let values = values.lock().unwrap();
    
    assert_eq!(*values, vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);