Rust初学者大多会遇到这样的问题:

  • 为什么同一资源不可被同时可变借用和不可变借用?
  • 为什么Rc一定只能是只读的,一定要配合std::cell系列(Cell,RefCell,UnsafeCell)才能提供可变性?为什么不设计一个可变的Rc?
  • 为什么Mutex/RwLock一般都会配合Arc使用?

    ……

这一类借用规则的问题,实际上都可以通过另一种思路来很好地解答,当然这也是很多大佬一定程度上认可的理解方式:

Rust中的借用,分为不可变借用共享借用,和可变借用独占借用

无论在教程中,还是语法中,我们都用可变性来区分二种借用,最开始,最直观的理解:

  • 因为是可变借用,多方借用会导致冲突,因此可变借用是独占的。
  • 因为是不可变借用,多方借用只读数据不会导致冲突,因此不可变借用是可共享的。

但是我们可以试着换一个方向去思考,用独占性去区分两种借用,很多问题便可以轻易理解:

  • 因为是独占借用,对资源的任何形式的访问都只能有一方可以被允许,所以对它的改变是安全无害的。
  • 因为是共享借用,对资源的访问可以有多方共同进行,所以对其中任何一方而言,来自其他方的改变是不可控的,所以对它的改变并不是安全无害的,因此它只允许只读访问。

这样的思考方式从“可变性==>独占性”换成了“独占性==>可变性”,首先就直观地解释了“同一资源不可同时被可变借用和不可变借用”的问题,因为“独占借用”从字面上就不可能跟其他任何形式的借用共存。

再说到Rc/Arc。Rc是通过引用计数来提供安全的共享访问的只能指针,在C++中本就叫做"shared_ptr",从逻辑上就是提供共享访问的工具,不应被任何一方独占,因此也理应只提供共享借用。而Arc就是线程安全版的Rc。

无论是std::cell系列还是Mutex/RwLock,它们的目的都一致:为共享资源提供安全的可变访问。由于既需要共享,也需要可变,因此无法用“独占=可变,共享=不可变”的类型模型去编译期检查访问的安全性,只能在运行时通过实际的行为去动态检查,保证“同一时间,一个资源只可以被一方可变访问,或被多方不可变访问”的原则。只是它们的行为略有不同:

  • UnsafeCell仅仅是一层包装壳,在对本身的访问不需要所有权或独占借用,仅提供共享借用的前提下,提供对内含资源的独占引用访问,因为没有任何策略保证访问的安全,因此对其的操作是unsafe的。
  • Cell屏蔽掉了UnsafeCell的引用访问,只提供存取访问。由于在单线程下,调用函数即完全交出控制权,存取都可被视为原子操作,而资源本身也从一个静态的资源变成了一个需要操作去存取的读写对象,因此自然也保证了安全访问的原则。
  • RefCell在UnsafeCell的基础上,以性能为代价,加入了运行时检查机制以提供安全的引用访问。由于引用可以在调用结束后持续地被持有,因此需要guard(通过自身的RAII来控制目标资源的占用与解除占用的结构)来运行时监控当前资源被访问的形式和数量,在打破安全访问的原则时及时抛出panic来避免ub。
  • RwLock是线程安全版的RefCell,通过调用系统底层的线程锁来实现线程安全,在打破安全访问原则时阻塞后续的访问而不是panic,以等待目前的占用解除。
  • Mutex是只读访问互斥版的RwLock,即使不存在可写访问,仍然会在已有只读访问占用时阻塞后续的只读访问。

不难看出,很多情况下,Arc<RwLock>的组合实际上跟Rc<RefCell>的逻辑是一致的:在需要共享的可变资源时,先用Rc/Arc控制资源的生命周期,再用RefCell/RwLock来控制资源的访问安全,区别在于是否为跨线程访问提供支持。

综上所述,以个人经验来讲,在习惯上以独占借用/共享借用的视角来分析,而不是可变借用/不可变借用,更有助于理解借用规则的实质,希望以此可以给初接触Rust的同行一些启发。

Rust借用机制的理解分析的更多相关文章

  1. Springboot学习04-默认错误页面加载机制源码分析

    Springboot学习04-默认错误页面加载机制源码分析 前沿 希望通过本文的学习,对错误页面的加载机制有这更神的理解 正文 1-Springboot错误页面展示 2-Springboot默认错误处 ...

  2. Android事件分发机制源码分析

    Android事件分发机制源码分析 Android事件分发机制源码分析 Part1事件来源以及传递顺序 Activity分发事件源码 PhoneWindow分发事件源码 小结 Part2ViewGro ...

  3. Redis数据持久化机制AOF原理分析一---转

    http://blog.csdn.net/acceptedxukai/article/details/18136903 http://blog.csdn.net/acceptedxukai/artic ...

  4. 浅谈 Attention 机制的理解

    什么是注意力机制? 注意力机制模仿了生物观察行为的内部过程,即一种将内部经验和外部感觉对齐从而增加部分区域的观察精细度的机制.例如人的视觉在处理一张图片时,会通过快速扫描全局图像,获得需要重点关注的目 ...

  5. [转]as3事件流机制彻底理解

    题记: 看过网上一些as3事件流的教程,觉得大多都讲得不甚清楚,让人不能直观的理解事件流.而这篇教程以将事件流过程比喻成捕鱼过程,形象简单. 在此基础上对于as3事件流总算有了全面的理解.事件流机制说 ...

  6. Linux内核OOM机制的详细分析(转)

    Linux 内核 有个机制叫OOM killer(Out-Of-Memory killer),该机制会监控那些占用内存过大,尤其是瞬间很快消耗大量内存的进程,为了 防止内存耗尽而内核会把该进程杀掉.典 ...

  7. 我对asp.net运行机制的理解

    有一本书叫<asp.net 本质论>,作者名叫冠军.我看了几次,都没有坚持看下来.这次连续看完了前三章,然后参考网上的资料,总结下我对.net运行机制的理解. 先上两张图: 看着这两张图, ...

  8. JDK动态代理深入理解分析并手写简易JDK动态代理(下)

    原文同步发表至个人博客[夜月归途] 原文链接:http://www.guitu18.com/se/java/2019-01-05/27.html 作者:夜月归途 出处:http://www.guitu ...

  9. JDK动态代理深入理解分析并手写简易JDK动态代理(上)

    原文同步发表至个人博客[夜月归途] 原文链接:http://www.guitu18.com/se/java/2019-01-03/27.html 作者:夜月归途 出处:http://www.guitu ...

随机推荐

  1. fiddler工具介绍及证书设置

    fiddler 目录 1.Fiddler介绍 01.介绍 02.简单使用 03.结果状态码 介绍完了,接下来就到证书了 2.Fiddler证书设置 这就是fiddler证书设置的全部步骤了 1.Fid ...

  2. spring 之BeanPostProcessor&BeanFactoryPostProcessor

    http://www.cnblogs.com/sishang/p/6576665.html https://www.cnblogs.com/sishang/p/6588542.html

  3. canvas的简单绘制及设置

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> </head> ...

  4. Java多线程--CAS

    在Java多线程并发的情况下同时对一个变量进行操作会出现线程安全的问题,假如我们现在使用20个线程对一个变量不停累加1,代码如下: 1 public class ThreadDemo implemen ...

  5. Oracle学习(五)DBLINK

    一.DBLINK学习 目的:为了解决跨库访问的需求. 场景如下:tnsnames.ora(oracle的库配置文件)下配置了2个库的环境地址,现在要实现跨库访问. PS:DBLINK和是否同一个主机无 ...

  6. 图形渲染的大致过程和关于OpenGL渲染管线的一些零碎知识,openglpipeline,vao,vbo,ebo.

    重要!!! OpenGL新人一枚,希望可以再此和大家分享有用的知识,少走弯路 文章会定期更新,把前面几段已经整理过的知识更完后,接下来每周至少会更两次. 文章如果有不对的,理解错误的地方,也非常希望在 ...

  7. UOS服务器常见问题

    UOS服务器安装完成之后,xshell工具无法远程, 描述 我安装完系统后,用xshell工具无法远程,必须在系统上才能进去我是通过centos7的kvm虚拟工具上刷的统信的系统,安装方式: 最小化安 ...

  8. Elasticsearch数据库 | Elasticsearch-7.5.0应用基础实战

    Elasticsearch 是一个可用于分布式以及符合RESTful 风格的搜索和数据分析引擎.-- Elastic Stack 官网 关于Elasticsearch的"爱恨情仇" ...

  9. 我们解决了如何将视频转换为HEVC / H.265和AVC / H.264

    LEADTOOLS Recognition Imaging SDK是精选的LEADTOOLS SDK功能集,旨在在企业级文档自动化解决方案中构建端到端文档成像应用程序,这些解决方案需要OCR,MICR ...

  10. LeetCode刷题总结-动态规划篇

    本文总结LeetCode上有动态规划的算法题,推荐刷题总数为54道.具体考点分析如下图: 1.中心扩展法 题号:132. 分割回文串 II,难度困难 2.背包问题 题号:140. 单词拆分 II,难度 ...