• rust学习-Arc


    背景介绍

    线程安全的引用计数指针。 “Arc”代表“原子引用计数 Atomically Reference Counted”。

    Arc 类型提供在堆中分配的 T 类型值的共享所有权(shared ownership)。在 Arc 上调用克隆会生成一个新的 Arc 实例,该实例指向堆上与源 Arc 相同的分配,同时增加引用计数。当指向给定分配的最后一个 Arc 指针被销毁时,存储在该分配中的值(通常称为“内部值”)也会被删除。

    Rust 中的共享引用默认不允许mutation,Arc 也不例外:通常无法获得对 Arc 内某些内容的可变引用。如果需要通过 Arc 进行mutate,请使用 Mutex、RwLock 或 Atomic 类型之一。

    注意:此类型仅在支持原子加载和指针存储的平台(platforms that support atomic loads and stores of pointers)上可用,其中包括所有支持 std crate 的平台,但不包括所有仅支持 alloc 的平台。这可以在编译时使用 #[cfg(target_has_atomic = “ptr”)] 检测到。

    与 Rc 不同,Arc 使用原子操作进行引用计数。这意味着它是线程安全的。缺点disadvantage是原子操作比普通内存访问(ordinary memory accesses)更昂贵。如果不在线程之间共享引用计数分配,请考虑使用 Rc 来降低开销。 Rc 是一个安全的默认值,因为编译器会捕获在线程之间发送 Rc 的任何尝试(catch any attempt to send an Rc between threads)。但是,library可能会选择 Arc 以便为library使用者提供更大的灵活性。

    只要 T 实现了Send 和 Sync,Arc 就会实现Send 和 Sync。
    为什么不能将非线程安全类型 T 放入 Arc 中以使其成为线程安全的?
    乍一看这可能有点违反直觉(a bit counter-intuitive):
    毕竟,难道不是 Arc 线程安全的重点吗( isn’t the point of Arc thread safety? )?
    关键点是:Arc 使得对同一数据拥有多个所有权(have multiple ownership of the same data)是线程安全的,但它并没有为其数据添加线程安全性。
    考虑 Arc。 RefCell 不是Sync的,如果 Arc 始终是Send,则 Arc 也会如此。但这样我们就会遇到一个问题:RefCell 不是线程安全的;它使用非原子操作跟踪借用计数(keeps track of the borrowing count using non-atomic operations)。

    最后,这意味着可能需要将 Arc 与某种 std::sync 类型(通常是 Mutex)配对使用(pair Arc with some sort of std::sync type, usually Mutex)。

    Breaking cycles with Weak

    用 Weak 打破cycle
    downgrade 方法可用于创建非拥有的 Weak 指针(a non-owning Weak pointer)。弱指针(Weak pointer)可以升级为 Arc,但如果存储在分配(allocation)中的值已被删除,这将返回 None。换句话说,弱指针不会使分配内的值保持 active 状态;但是,它们确实使allocation(值的后端存储?)保持 active 状态(they do keep the allocation (the backing store for the value) alive)。

    Arc 指针之间的循环永远不会被释放。因此,使用Weak来打破循环。例如,一棵树可以具有从父节点到子节点的强Arc指针,以及从子节点返回到其父节点的Weak指针。

    创建

    使用 Clone trait 给 Arc 和 Weak

    impl<T> Clone for Arc<T>
    where
        T: ?Sized,
    
    • 1
    • 2
    • 3
    fn clone(&self) -> Arc<T>
    use std::sync::Arc;
    let foo = Arc::new(vec![1.0, 2.0, 3.0]);
    
    // 两种方式等价
    let a = foo.clone();
    let b = Arc::clone(&foo);
    // a, b, and foo are all Arcs that point to the same memory location
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    Deref behavior

    在 Arc 上可以调用 T 的方法,因为 Arc 自动解引用到 T
    为了避免与 T 的方法发生名称冲突,Arc 本身的方法是关联函数,使用完全限定语法(fully qualified syntax)进行调用:

    use std::sync:
    • 相关阅读:
      面试总结:H5 移动 web 开发(H5 新特性、CSS3 新特性、如何实现双飞翼(圣杯)布局)
      【笔记:模拟MOS集成电路】偏置电路(基本原理+结构分析)
      滥用出资人权利的后果是什么
      浅谈分散式存储项目MEMO
      elasticsearch-head浏览器(google)插件安装使用
      leetcode 刷题 log day 46(背包总结篇
      通宵三天 我做了一个超级好玩的中秋节小游戏
      React之Hooks基础
      C/C++编程工具及实用小软件推荐
      【笔者感悟】笔者的工作感悟【二】
    • 原文地址:https://blog.csdn.net/wangkai6666/article/details/133348235