Rustには従来のガベージコレクタがないため、複雑な構造体の所有権を管理するためにスマートポインタを使用します。最も一般的に使用されるものは次のとおりです:
Box<T> — ヒープにオブジェクトのメモリを割り当て、その所有権を移動します。データのサイズがコンパイル時に不明な場合や、移動可能だがユニークなリソースが必要な場合に使用されます。
Rc<T>(Reference Counted) — 参照カウントを使用し、複数の変数が不変データの所有権を「共有」できるようにします(単一スレッドコンテキストのみ)。
Arc<T>(Atomic Reference Counted) — こちらも参照カウントを実装しますが、アトミックです。マルチスレッドプログラムでの使用が許可されています。
RefCell<T> — 実行時に「内部可変」所有権を提供し、不変の参照を介してさえ内容を変更できるようにしますが、単一スレッドのみ(スレッドセーフではありません!)。
例:
use std::rc::Rc; let a = Rc::new(vec![1,2,3]); let b = Rc::clone(&a); // 現在、aとbの両方が同じデータの所有者です
すべてのスレッドがデータを読むだけの場合、Rc<T>をマルチスレッドコードで使用できますか?説明してください。
答え:いいえ、できません! Rc<T>はデータへの不変アクセスのみを許可しますが、Rc<T>自体はスレッドセーフではなく、内部の参照カウントがデータレースから保護されていないためです。これにはArc<T>が必要です — その内部カウンタはスレッドセーフです。
例:
// 次のコードはコンパイルされません! use std::thread; use std::rc::Rc; let five = Rc::new(5); for _ in 0..10 { let five = Rc::clone(&five); thread::spawn(move || { println!("{}", five); }); }
物語
物語
物語
ビジネスロジックモジュールで、RefCell<T>を使用してデータへの可変アクセスを提供しましたが、これらのデータはArc<T>を介してスレッド間で渡されていました。しかし、RefCell<T>とArc<T>を組み合わせようとした結果、データレースと実行時のパニックが発生しました。スレッドセーフなオプションのためには、RefCell<T>の代わりにMutex<T>またはRwLock<T>を使用する必要がありました。