Arc
Arc<T> は、Arc::clone を使って共有の読み取り専用所有権を実現します:
// Copyright 2024 Google LLC // SPDX-License-Identifier: Apache-2.0 use std::sync::Arc; use std::thread; /// どのスレッドがこれをドロップしたかを出力する構造体。 #[derive(Debug)] struct WhereDropped(Vec<i32>); impl Drop for WhereDropped { fn drop(&mut self) { println!("Dropped by {:?}", thread::current().id()) } } fn main() { let v = Arc::new(WhereDropped(vec![10, 20, 30])); let mut handles = Vec::new(); for i in 0..5 { let v = Arc::clone(&v); handles.push(thread::spawn(move || { // 0〜500ms スリープします。 std::thread::sleep(std::time::Duration::from_millis(500 - i * 100)); let thread_id = thread::current().id(); println!("{thread_id:?}: {v:?}"); })); } // これで、生成されたスレッドだけが `v` のクローンを保持します。 drop(v); // 最後に生成されたスレッドが終了すると、`v` の内容がドロップされます。 handles.into_iter().for_each(|h| h.join().unwrap()); }
Arcは “Atomic Reference Counted” の略で、アトミック操作を使用するRcのスレッドセーフ版です。Arc<T>は、TがCloneを実装しているかどうかに関係なくCloneを実装します。TがSendとSyncの両方を実装している場合に限り、それらも実装します。Arc::clone()には実行されるアトミック操作のコストがありますが、その後のTの利用自体にはコストがかかりません。- 参照サイクルに注意してください。
Arcはそれらを検出するためのガベージコレクタを使用しません。std::sync::Weakが役立ちます。