【Rust】Arcとはどういう時に使用するか?

Arc(std::sync::Arc)は、複数スレッドで安全に共有できる参照カウント付きスマートポインタ

### Arcはいつ使うか?
– 複数スレッドで同じデータを共有したい時
– かつ、読み取り専用 or 内部で排他制御する設計の時

use std::sync::Arc;
use std::thread;

fn main() {
    let data = Arc::new(vec![1, 2, 3]);

    let mut handles = vec![];

    for i in 0..3  {
        let data_clone = Arc::clone(&data);
        let handle = thread::spawn(move || {
            println!("Thread {} sees: {:?}", i, data_clone);
        });
        handles.push(handle);
    }

    for handle in handles {
        handle.join().unwrap();
    }
}

$ ./playground
Thread 0 sees: [1, 2, 3]
Thread 1 sees: [1, 2, 3]
Thread 2 sees: [1, 2, 3]

同じようなコード

use std::sync::{Arc};
use std::thread;

fn main() {
    let data = Arc::new(1);

    let mut handles = vec![];

    for i in 0..3  {
        let data_clone = Arc::clone(&data);
        let handle = thread::spawn(move || {
            println!("{}", i + *data_clone);
        });
        handles.push(handle);
    }

    for handle in handles {
        handle.join().unwrap();
    }
}

### 書き換えたい時

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

fn main() {
    let counter = Arc::new(Mutex::new(0));

    let mut handles = vec![];

    for _ in 0..10  {
        let counter = Arc::clone(&counter);
        let handle = thread::spawn(move || {
            let mut num = counter.lock().unwrap();
            *num += 1;
        });
        handles.push(handle);
    }

    for handle in handles {
        handle.join().unwrap();
    }

    println!("Final counter: {}", *counter.lock().unwrap());
}

単なるデータのカウントアップだけなら、以下のようなシングルスレッドの方が効率的だが、

fn main() {
    let mut counter = 0;

    for _ in 0..10 {
        counter += 1;
    } 

    println!("{}", counter);
}

並列ダウンロード、Webサーバなどでは、圧倒的に複数スレッドの方が効率が良い。
それでArcやmutexが使用される。
なるほど〜