RustのArc<T>
は、Sendを満たすためにTがSendとSyncの両方を満たさなければならないと、ドキュメントに書いてありました。
なぜSendの場合はTがSendのみ、Syncの場合はTがSyncのみ実装していれば良い、というわけではないのでしょうか?私は自分なりに考えたところ、RefCellといったSendのみ実装するものをArcでラップした際に問題が生じるからではないか、という結論となりましたが、これであってますでしょうか?ご教授お願いしたいです。
私は自分なりに考えたところ、以下のコードを書いてみました。
rust
1fn main() { 2 // RefCellをArcでラップする。 3 let cell = std::sync::Arc::new(std::cell::RefCell::new(42)); 4 5 let handle = std::thread::spawn(move || { 6 // cellの所有権を移動して、その値を使う。 7 println!("{}", cell.borrow()); 8 }); 9 10 handle.join().unwrap(); 11}
このコードでは、RefCellをArcでラップしてメインスレッドではないスレッドでRefCellの中の値42の参照を作ろうとしています。
ここで、Syncを実装していないということは、&T
がSendではないということです。その上で、それにも関わらず、このコードではArc
のDerefトレイトによりRefCellの参照がcell.borrow()
にて作られてしまっていて、メインスレッドではない場所でRefCell
へのアクセスが発生してしまっています。そのため、このコードはコンパイルが通ってはいけないと私は考えました。
この時、cell
の値であるArc<RefCell<i32>>
がSendではないので実際にもコンパイルは通らないのですが、それはArc<T>
がSendを満たすためにSendとSyncがTに実装されていないといけないがために、このコンパイルエラーが実現した、と考察できます。
つまり、RefCellなどのSendのみ実装するものをArcでラップした際に問題が発生するため、Arc<T>がSendになるにはTがSend + Syncである必要がある、と考えました。
私の質問は、なぜArc<T>
がSendを満たすにはTがSendとSyncの両方を満たしてなければならないのか、というものでした。そこで自分なりに考えたところ、RefCellといったものをArcでラップしてスレッド間の移動をした際に問題が生じてしまうから、という結論がでました。私の質問への答えは、これであってますでしょうか?それとも、他が理由でしょうか?

回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2025/05/11 01:08 編集