在 Rust 中没有传统的垃圾收集器,因此使用智能指针 (smart pointers) 来管理复杂结构的所有权。最常用的包括:
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> 结合使用导致了竞争条件和运行时恐慌。对于线程安全的选择,应使用 Mutex<T> 或 RwLock<T> 代替 RefCell<T>。