需要全面了解Rust的单元格和引用计数类型


73

Rust标准库中有几种包装器类型:

据我了解,这些包装器提供了比简单参考更多的可能性。虽然我了解一些基本知识,但看不到整个图片。

他们到底在做什么?细胞和参考计数家族是否提供正交或相似特征?


5
请描述什么你不明白。您链接到的文档已有数百(或数千)个人阅读,并且可能有数十至数百个人对此作出了贡献。我们能说什么与已经说的有什么不同,特别是如果您不告诉我们您不了解的内容呢?
Shepmaster

1
@Shepmaster文档中的解释涉及内部可变性。这个概念对我来说还不清楚。也许我的问题也不清楚。
Boiethios

3
快速的互联网搜索在书中找到了有关内部可变性的一章,一篇博客文章以及一个SO问题。也许现在您知道不清楚的地方,可以进行一些研究并更新您的问题。
Shepmaster

Answers:


141

Rust中有两个基本概念:

  • 所有权,
  • 可变性。

的各种指针类型(BoxRcArc)所关心的所有权:它们允许控制是否有单个或多个所有者的单个对象。

在另一方面,各种细胞(CellRefCellMutexRwLockAtomicXXX)所关注的可变性


Rust的安全性的基本准则Aliasing XOR Mutability。也就是说,只有在对象内部没有显着引用的情况下,才可以安全地对其进行突变。

通常,借阅检查器会在编译时强制执行以下规则:

  • 如果您有&T,则&mut T范围内的同一对象也不能具有,
  • 如果您有&mut T,则您也不能在范围内对同一对象有任何引用。

但是,有时这不够灵活。有时您确实需要(或想要)具有对同一个对象的多个引用并对其进行突变的能力。输入单元格

的思想CellRefCell是允许在可变性混叠的存在以受控的方式

  • Cell 防止形成对内部的参照,避免悬挂的参照,
  • RefCell将“别名XOR可变性”的实施从编译时间转移到运行时。

有时将这种功能描述为提供内部可变性,也就是说,&T实际上可以改变从外部看起来不可变的对象的位置。

当这种可变性在多个线程扩展,您将改为使用MutexRwLockAtomicXXX; 它们提供相同的功能:

  • AtomicXXX只是Cell:没有提及内部,只是移进/移出,
  • RwLock公正RefCell:可以通过守卫获得对内饰的参考,
  • Mutex是简化版本,RwLock不区分只读保护和写保护;因此在概念上类似于RefCell仅使用borrow_mut方法的。

如果您来自C ++背景:

  • Boxunique_ptr
  • Arcshared_ptr
  • Rc是的非线程安全版本shared_ptr

单元提供与相似的功能mutable,除了额外的保证以避免混叠问题。可以Cellstd::atomicRefCell视为非线程安全版本std::shared_mutex(如果采用了锁定,则抛出该异常而不是阻塞该异常)。


2
谢谢你这么多,你正好回答我所有的关于“复杂”的类型锈困惑。与C ++的比较也很完美。
Boiethios

3
@Boiethios:是的,就是这样。每个引用/指针都是真实数据的“别名”(毕竟,同一“人”的不同名称就是别名),并且通过扩展,我们在软件中讨论当给定存在多个别名时的别名。时间。
Matthieu M.

3
这本书的第一版对此做了一章。这是在重写中丢失的内容之一,我认为这很不幸-也许应该将其制成附录或类似内容
trentcl

6
如果别名XOR可变性是安全性的规则,是否意味着(非别名)AND(非可变性)是不安全的?但是可以肯定的是,如果没有别名并且没有可变性,那完全安全吗?我认为您想要的不是XOR。
Lii

11
口号也许应该使用NAND而不是XOR:P
Rufflewind '17

15

感谢Matthieu的良好回答,这是一个图表,可以帮助人们找到所需的包装纸:

+-----------+
| 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>> |
                                           +================+
  1. 在这种情况下,T可以替换为Box<T>
  2. 使用AtomicT时,T是一个bool或数

要知道是否应使用Mutexor RwLock,请参阅此相关问题

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.