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が使用される。
なるほど〜