Rust 中的克隆 Arc
这篇文章是关于原子引用计数(Arc)
,一个处理一个对象(类型 T
)并允许共享所有权的代理。我们还将学习使用 clone()
函数创建一个新的拥有的句柄,它可以移动到一个新线程。
此外,我们将借助示例了解共享所有权。
Rust 中的共享所有权
共享所有权是指多个名称对单个对象的所有权。例如,你为家人购买的狗。
你不能指定一个明确的所有者,因为所有家庭成员都共享该狗的所有权。我们必须认识到,如果其中一个家庭成员死了,狗不会和他们一起死。
另一方面,如果所有家庭成员都死了,狗就会死。基本原理是这样的:每个人都拥有一些东西,最后一个站着清理它。
可能仅使用传统的 Rust 技术不足以描述这种共享所有权形式。例如,你必须始终为狗指定一个主人,而其他人只能指代狗。
Rust 中的 Rc
和 Arc
允许共享所有权。
在 Rust 中克隆 Arc
的效果
Arc<T>
类型表示在跳跃中分配的共享介质中类型 T
值的所有权。当引用计数增加时,会形成一个新的 Arc
实例,连接到与原始 Arc
相同的堆分配。
在 Rust 中使用 Rc
对内存的影响
let nil = Rc::new(Dog { legs: 4 });
在内存中,狗生活在堆上,计数为 1
(计数器设置为 1
)。因此,计数器知道对象数据在当前情况下拥有的所有者数量。
而 1
是正确的,因为 nil
是目前拥有狗的人。
clone()
Rust 中的 Rc
let esh = nil.clone();
let kat = nil.clone();
由于这段代码,狗只在内存中存在一次。然而,引用计数增加到 3
,这是合乎逻辑的,因为狗有三个主人。
这三个所有者引用堆上的内存块。这样,Rust book 调用了所有的句柄:每个所有者都拥有底层对象。
我们需要知道 Arc<T>
上的 clone()
不会克隆 T
而是创建另一个拥有的句柄。它只是一个指针,其行为就像它持有底层对象一样。
Rust 中 Arc<T>
和 Rc<T>
的区别
多个线程可以使用 Arc
以原子方式增加和减少计数器,而不会出现问题。因此,Arc
不限于线程边界。
然而,Arc
并不意味着提供来自多个所有者的同时可变访问。因此,Rc<T>
用于多重所有权,而 Arc<T>
用于超出线程边界的多重所有权。
Rc<T>
允许我们拥有多个指向同一数据的指针,并且在所有指针被释放后数据被释放。