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