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]);