Rust标准库中有几种包装类型:
std::cell
module中的单元格:Cell
和RefCell
Rc
和Arc
。std::sync
module中的类型:Mutex
或AtomicBool
例如据我所知,这些包装器提供了比简单参考更多的可能性。虽然我理解了一些基础知识,但我看不到整体情况。
他们到底做了什么?细胞和参考计数的家族是否提供正交或类似的特征?
答案 0 :(得分:119)
Rust中有两个基本概念:
各种指针类型(Box
,Rc
,Arc
)与所有权有关:它们允许控制是否有单个或多个所有者单个对象。
另一方面,各种单元格(Cell
,RefCell
,Mutex
,RwLock
,AtomicXXX
)与 Mutability < / em>的
Rust的安全性的基本规则是别名XOR可变性。也就是说,如果没有对其内部的未完成引用,则只能安全地改变对象。
此规则通常在编译时由借用检查程序执行:
&T
,则您不能在范围内对同一个对象&mut T
,&mut T
,你也不能在范围内对同一个对象有任何引用。然而,有时候,这还不够灵活。有时你需要(或想要)能够对同一个对象进行多次引用然后改变它。输入单元格。
Cell
和RefCell
的想法是允许以受控方式存在别名的可变性:
Cell
阻止形成对其内部的引用,避免悬空引用,RefCell
将别名XOR Mutability 的强制执行从编译时转移到运行时。此功能有时被描述为提供内部可变性,这是一个实际上可以突变从外部(&T
)看起来不可变的对象。
当此可变性扩展到多个线程时,您将使用Mutex
,RwLock
或AtomicXXX
;它们提供相同的功能:
AtomicXXX
只是Cell
:没有引用内部,只是移入/移出,RwLock
只是RefCell
:可以通过警卫获取对内部的引用,Mutex
是RwLock
的简化版本,不区分只读后卫和写保护;因此在概念上类似于只有RefCell
方法的borrow_mut
。如果你来自C ++背景:
Box
是unique_ptr
,Arc
是shared_ptr
,Rc
是shared_ptr
的非线程安全版本。细胞提供与mutable
类似的功能,除了有额外的保证以避免混叠问题;将Cell
视为std::atomic
,将RefCell
视为std::shared_mutex
的非线程安全版本(如果采取锁定则抛出而不是阻止)。
答案 1 :(得分:6)
感谢Matthieu's good answer,这是一个帮助人们找到所需包装器的图表:
+-----------+
| Ownership |
+--+--------+ +================+
| +-Static----->| T |(1)
| | +================+
| |
| | +================+
| +-----------+ | Local Val| Cell<T> |(1)
+-Unique-->| Borrowing +--+-Dynamic---->|----------------|
| +-----------+ | Ref| RefCell<T> |(1)
| | +================+
| |
| | +================+
| | Threaded | AtomicT |(2)
| +-Dynamic---->|----------------|
| | Mutex<T> |(1)
| | RwLock<T> |(1)
| +================+
|
|
| +================+
| +-No--------->| Rc<T> |
| | +================+
| Locally +-----------+ |
+-Shared-->| Mutable? +--+ +================+
| +-----------+ | Val| Rc<Cell<T>> |
| +-Yes-------->|----------------|
| Ref| Rc<RefCell<T>> |
| +================+
|
|
| +================+
| +-No--------->| Arc<T> |
| | +================+
| Shared +-----------+ |
+-Between->| Mutable? +--+ +================+
Threads +-----------+ | | Arc<AtomicT> |(2)
+-Yes-------->|----------------|
| Arc<Mutex<T>> |
| Arc<RwLock<T>> |
+================+
T
可以替换为Box<T>
T
为bool
或数字AtomicT
醇>
要知道您是应该使用Mutex
还是RwLock
,请参阅this related question。