Struct alloc::sync::Arc

1.0.0 · source ·
pub struct Arc<T: ?Sized> { /* private fields */ }
Expand description

线程安全的引用计数指针。Arc 代表原子引用计数。

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

默认情况下,Rust 中的共享引用不允许可变的,Arc 也不例外:您通常无法获得 Arc 内部内容的可变引用。如果需要通过 Arc 进行可变的,请使用 MutexRwLockAtomic 类型之一。

Note: 此类型仅在支持原子加载和指针存储的平台上可用,其中包括支持 std crate 的所有平台,但并非所有仅支持 alloc 的平台。 这可以在编译时使用 #[cfg(target_has_atomic = "ptr")] 检测到。

线程安全

Rc<T> 不同,Arc<T> 使用原子操作进行引用计数。这意味着它是线程安全的。缺点是原子操作比普通的内存访问更昂贵。如果您不共享线程之间的引用计数分配,请考虑使用 Rc<T> 来降低开销。 Rc<T> 是一个安全的默认值,因为编译器会捕获在线程之间发送 Rc<T> 的任何尝试。 但是,一个库可能会选择 Arc<T>,以便为库的消费者提供更大的灵活性。

只要 T 实现 SendSyncArc<T> 就会实现 SendSync。 为什么不能在 Arc<T> 中放置非线程安全类型 T 使其成为线程安全的? 起初这可能有点违反直觉:毕竟,Arc<T> 的重点不就是线程安全吗? 关键在于: Arc<T> 使具有同一数据的多个所有权成为线程安全的,但并未为其数据增加线程安全。

考虑 Arc<RefCell<T>>RefCell<T> 不是 Sync,如果 Arc<T> 总是 Send,那么 Arc<RefCell<T>> 也是。 但是然后我们会遇到一个问题: RefCell<T> 不是线程安全的; 它使用非原子操作来跟踪借用计数。

最后,这意味着您可能需要将 Arc<T> 与某种 std::sync 类型 (通常为 Mutex<T>) 配对。

Weak 的中断循环

downgrade 方法可用于创建非所有者 Weak 指针。Weak 指针可以 upgradeArc,但如果存储在分配中的值已经被丢弃,这将返回 None。 换句话说,Weak 指针不会使分配内部的值保持活动状态。然而,它们确实使分配(值的后备存储)保持活动状态。

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

克隆引用

使用为 Arc<T>Weak<T> 实现的 Clone trait 从现有的引用计数指针创建新的引用。

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 和 foo 都是指向同一内存位置的 Arc
Run

Deref 行为

Arc<T> 自动取消对 T 的引用 (通过 Deref trait),因此您可以在类型为 Arc<T> 的值上调用 T 的方法。为了避免与 T 的方法名称冲突,Arc<T> 本身的方法是关联函数,使用 完全限定语法 调用:

use std::sync::Arc;

let my_arc = Arc::new(());
let my_weak = Arc::downgrade(&my_arc);
Run

Arc<T> 也可以使用完全限定语法来调用诸如 Clone 之类的 traits 实现。 有些人喜欢使用完全限定的语法,而另一些人则喜欢使用方法调用语法。

use std::sync::Arc;

let arc = Arc::new(());
// 方法调用语法
let arc2 = arc.clone();
// 完全限定的语法
let arc3 = Arc::clone(&arc);
Run

Weak<T> 不会自动解引用到 T,因为内部值可能已经被丢弃了。

Examples

在线程之间共享一些不可变数据:

use std::sync::Arc;
use std::thread;

let five = Arc::new(5);

for _ in 0..10 {
    let five = Arc::clone(&five);

    thread::spawn(move || {
        println!("{five:?}");
    });
}
Run

共享可变的 AtomicUsize

use std::sync::Arc;
use std::sync::atomic::{AtomicUsize, Ordering};
use std::thread;

let val = Arc::new(AtomicUsize::new(5));

for _ in 0..10 {
    let val = Arc::clone(&val);

    thread::spawn(move || {
        let v = val.fetch_add(1, Ordering::SeqCst);
        println!("{v:?}");
    });
}
Run

有关更多一般引用计数示例,请参见 rc 文档

Implementations§

source§

impl<T> Arc<T>

source

pub fn new(data: T) -> Arc<T>

创建一个新的 Arc<T>

Examples
use std::sync::Arc;

let five = Arc::new(5);
Run
1.60.0 · source

pub fn new_cyclic<F>(data_fn: F) -> Arc<T>where F: FnOnce(&Weak<T>) -> T,

创建一个新的 Arc<T>,同时给您一个分配的 Weak<T>,以允许您创建一个 T,它持有一个指向自身的弱指针。

通常,直接或间接循环引用自身的结构体不应该对自身持有强引用以防止内存泄漏。 使用这个函数,您可以在 T 的初始化过程中,在 Arc<T> 创建之前访问弱指针,这样您就可以将它克隆并存储在 T 中。

new_cyclic 先给 Arc<T> 分配托管分配,然后调用您的闭包,给这个分配一个 Weak<T>,然后再把您的闭包返回的 T 放入分配中,完成 Arc<T> 的构建。

由于新的 Arc<T>Arc<T>::new_cyclic 返回之前尚未完全构造,因此在闭包内的弱引用上调用 upgrade 将失败并导致 None 值。

Panics

如果 data_fn 发生 panic,panic 会传播给调用者,而临时的 Weak<T> 会被正常丢弃。

Example
use std::sync::{Arc, Weak};

struct Gadget {
    me: Weak<Gadget>,
}

impl Gadget {
    /// 创建一个引用计数的 Gadget。
    fn new() -> Arc<Self> {
        // `me` 是指向我们正在构建的 `Arc` 的新分配的 `Weak<Gadget>`。
        Arc::new_cyclic(|me| {
            // 在此处创建实际的结构体。
            Gadget { me: me.clone() }
        })
    }

    /// 返回一个指向 Self 的引用计数指针。
    fn me(&self) -> Arc<Self> {
        self.me.upgrade().unwrap()
    }
}
Run
source

pub fn new_uninit() -> Arc<MaybeUninit<T>>

🔬This is a nightly-only experimental API. (new_uninit #63291)

创建一个具有未初始化内容的新 Arc

Examples
#![feature(new_uninit)]
#![feature(get_mut_unchecked)]

use std::sync::Arc;

let mut five = Arc::<u32>::new_uninit();

// 延迟初始化:
Arc::get_mut(&mut five).unwrap().write(5);

let five = unsafe { five.assume_init() };

assert_eq!(*five, 5)
Run
source

pub fn new_zeroed() -> Arc<MaybeUninit<T>>

🔬This is a nightly-only experimental API. (new_uninit #63291)

创建一个具有未初始化内容的新 Arc,并用 0 字节填充内存。

有关正确和不正确使用此方法的示例,请参见 MaybeUninit::zeroed

Examples
#![feature(new_uninit)]

use std::sync::Arc;

let zero = Arc::<u32>::new_zeroed();
let zero = unsafe { zero.assume_init() };

assert_eq!(*zero, 0)
Run
1.33.0 · source

pub fn pin(data: T) -> Pin<Arc<T>>

创建一个新的 Pin<Arc<T>>。 如果 T 未实现 Unpin,则 data 将被固定在内存中并且无法移动。

source

pub fn try_pin(data: T) -> Result<Pin<Arc<T>>, AllocError>

🔬This is a nightly-only experimental API. (allocator_api #32838)

创建一个新的 Pin<Arc<T>>,如果分配失败则返回错误。

source

pub fn try_new(data: T) -> Result<Arc<T>, AllocError>

🔬This is a nightly-only experimental API. (allocator_api #32838)

创建一个新的 Arc<T>,如果分配失败,则返回错误。

Examples
#![feature(allocator_api)]
use std::sync::Arc;

let five = Arc::try_new(5)?;
Run
source

pub fn try_new_uninit() -> Result<Arc<MaybeUninit<T>>, AllocError>

🔬This is a nightly-only experimental API. (allocator_api #32838)

构造具有未初始化内容的新 Arc,如果分配失败,则返回错误。

Examples
#![feature(new_uninit, allocator_api)]
#![feature(get_mut_unchecked)]

use std::sync::Arc;

let mut five = Arc::<u32>::try_new_uninit()?;

// 延迟初始化:
Arc::get_mut(&mut five).unwrap().write(5);

let five = unsafe { five.assume_init() };

assert_eq!(*five, 5);
Run
source

pub fn try_new_zeroed() -> Result<Arc<MaybeUninit<T>>, AllocError>

🔬This is a nightly-only experimental API. (allocator_api #32838)

创建一个具有未初始化内容的新 Arc,并用 0 字节填充内存,如果分配失败,则返回错误。

有关正确和不正确使用此方法的示例,请参见 MaybeUninit::zeroed

Examples
#![feature(new_uninit, allocator_api)]

use std::sync::Arc;

let zero = Arc::<u32>::try_new_zeroed()?;
let zero = unsafe { zero.assume_init() };

assert_eq!(*zero, 0);
Run
1.4.0 · source

pub fn try_unwrap(this: Self) -> Result<T, Self>

如果 Arc 正好有一个强引用,则返回内部值。

否则,返回的 Err 将与传入的 Arc 相同。

即使存在突出的弱引用,此操作也将成功。

如果您不想将 Arc 保留在 Err 外壳中,强烈建议改用 Arc::into_inner。 立即抛弃 Err 有效,载荷,就像在表达式 Arc::try_unwrap(this).ok() 中一样,仍然可以导致强制使用计数抛弃为零,Arc 的内部值为抛弃: 例如,如果两个线程都在并行中执行这个表达式,那么就有一个竞争条件。 线程可以首先检查它们是否通过 Arc::try_unwrap 拥有它们的 Arc 的最后一个克隆,然后在调用中将它们的 Arc 丢弃到 ok,将强引用计数从 2 降为零。

Examples
use std::sync::Arc;

let x = Arc::new(3);
assert_eq!(Arc::try_unwrap(x), Ok(3));

let x = Arc::new(4);
let _y = Arc::clone(&x);
assert_eq!(*Arc::try_unwrap(x).unwrap_err(), 4);
Run
1.70.0 · source

pub fn into_inner(this: Self) -> Option<T>

如果 Arc 正好有一个强引用,则返回内部值。

否则,返回 NoneArc 为丢弃。

即使存在突出的弱引用,此操作也将成功。

如果在这个 Arc 的每个克隆上调用 Arc::into_inner,则可以保证恰好有一个调用返回内部值。 这特别意味着内部值不是丢弃。

类似的表达式 Arc::try_unwrap(this).ok() 不提供这样的保证。 请参见下面的最后一个示例和 Arc::try_unwrap 的文档。

Examples

演示 Arc::into_inner 提供的保证的最小示例。

use std::sync::Arc;

let x = Arc::new(3);
let y = Arc::clone(&x);

// 两个线程在 `Arc` 的两个克隆上调用 `Arc::into_inner`:
let x_thread = std::thread::spawn(|| Arc::into_inner(x));
let y_thread = std::thread::spawn(|| Arc::into_inner(y));

let x_inner_value = x_thread.join().unwrap();
let y_inner_value = y_thread.join().unwrap();

// 其中一个线程保证接收到内部值:
assert!(matches!(
    (x_inner_value, y_inner_value),
    (None, Some(3)) | (Some(3), None)
));
// 如果线程改为调用 `Arc::try_unwrap(x).ok()` 和 `Arc::try_unwrap(y).ok()`,结果也可能是 `(None, None)`。
Run

一个更实际的例子证明需要 Arc::into_inner:

use std::sync::Arc;

// 使用 `Arc` 定义一个简单的单向链表:
#[derive(Clone)]
struct LinkedList<T>(Option<Arc<Node<T>>>);
struct Node<T>(T, Option<Arc<Node<T>>>);

// 丢掉依赖于 `Arc` 的析构函数的 long `LinkedList<T>` 会导致栈溢出。
// 为了防止这种情况,我们可以提供一个手动的 `Drop` 实现,它在循环中进行销毁:
impl<T> Drop for LinkedList<T> {
    fn drop(&mut self) {
        let mut link = self.0.take();
        while let Some(arc_node) = link.take() {
            if let Some(Node(_value, next)) = Arc::into_inner(arc_node) {
                link = next;
            }
        }
    }
}

// 省略 `new` 和 `push` 的实现
impl<T> LinkedList<T> {
    /* ... */
}

// 如果 `Drop` impl 使用的是 `Arc::try_unwrap(arc).ok()` 而不是 `Arc::into_inner(arc)`,则尽管手动 `Drop` impl,以下代码仍可能导致栈溢出。

// 创建一个长列表并克隆它
let mut x = LinkedList::new();
for i in 0..100000 {
    x.push(i); // 将 i 添加到 x 的前面
}
let y = x.clone();

// 丢弃并行中的克隆人
let x_thread = std::thread::spawn(|| drop(x));
let y_thread = std::thread::spawn(|| drop(y));
x_thread.join().unwrap();
y_thread.join().unwrap();
Run
source§

impl<T> Arc<[T]>

source

pub fn new_uninit_slice(len: usize) -> Arc<[MaybeUninit<T>]>

🔬This is a nightly-only experimental API. (new_uninit #63291)

创建一个具有未初始化内容的新原子引用计数切片。

Examples
#![feature(new_uninit)]
#![feature(get_mut_unchecked)]

use std::sync::Arc;

let mut values = Arc::<[u32]>::new_uninit_slice(3);

// 延迟初始化:
let data = Arc::get_mut(&mut values).unwrap();
data[0].write(1);
data[1].write(2);
data[2].write(3);

let values = unsafe { values.assume_init() };

assert_eq!(*values, [1, 2, 3])
Run
source

pub fn new_zeroed_slice(len: usize) -> Arc<[MaybeUninit<T>]>

🔬This is a nightly-only experimental API. (new_uninit #63291)

创建一个具有未初始化内容的新原子引用计数切片,内存中填充 0 字节。

有关正确和不正确使用此方法的示例,请参见 MaybeUninit::zeroed

Examples
#![feature(new_uninit)]

use std::sync::Arc;

let values = Arc::<[u32]>::new_zeroed_slice(3);
let values = unsafe { values.assume_init() };

assert_eq!(*values, [0, 0, 0])
Run
source§

impl<T> Arc<MaybeUninit<T>>

source

pub unsafe fn assume_init(self) -> Arc<T>

🔬This is a nightly-only experimental API. (new_uninit #63291)

转换为 Arc<T>

Safety

MaybeUninit::assume_init 一样,由调用者负责确保内部值确实处于初始化状态。

在内容尚未完全初始化时调用此方法会立即导致未定义的行为。

Examples
#![feature(new_uninit)]
#![feature(get_mut_unchecked)]

use std::sync::Arc;

let mut five = Arc::<u32>::new_uninit();

// 延迟初始化:
Arc::get_mut(&mut five).unwrap().write(5);

let five = unsafe { five.assume_init() };

assert_eq!(*five, 5)
Run
source§

impl<T> Arc<[MaybeUninit<T>]>

source

pub unsafe fn assume_init(self) -> Arc<[T]>

🔬This is a nightly-only experimental API. (new_uninit #63291)

转换为 Arc<[T]>

Safety

MaybeUninit::assume_init 一样,由调用者负责确保内部值确实处于初始化状态。

在内容尚未完全初始化时调用此方法会立即导致未定义的行为。

Examples
#![feature(new_uninit)]
#![feature(get_mut_unchecked)]

use std::sync::Arc;

let mut values = Arc::<[u32]>::new_uninit_slice(3);

// 延迟初始化:
let data = Arc::get_mut(&mut values).unwrap();
data[0].write(1);
data[1].write(2);
data[2].write(3);

let values = unsafe { values.assume_init() };

assert_eq!(*values, [1, 2, 3])
Run
source§

impl<T: ?Sized> Arc<T>

1.17.0 · source

pub fn into_raw(this: Self) -> *const T

消耗 Arc,返回包装的指针。

为避免内存泄漏,必须使用 Arc::from_raw 将指针转换回 Arc

Examples
use std::sync::Arc;

let x = Arc::new("hello".to_owned());
let x_ptr = Arc::into_raw(x);
assert_eq!(unsafe { &*x_ptr }, "hello");
Run
1.45.0 · source

pub fn as_ptr(this: &Self) -> *const T

为数据提供裸指针。

计数不会受到任何影响,并且不会消耗 Arc。 只要 Arc 中有大量计数,指针就有效。

Examples
use std::sync::Arc;

let x = Arc::new("hello".to_owned());
let y = Arc::clone(&x);
let x_ptr = Arc::as_ptr(&x);
assert_eq!(x_ptr, Arc::as_ptr(&y));
assert_eq!(unsafe { &*x_ptr }, "hello");
Run
1.17.0 · source

pub unsafe fn from_raw(ptr: *const T) -> Self

从裸指针构造 Arc<T>

裸指针必须事先由调用返回到 Arc<U>::into_raw,其中 U 的大小和对齐方式必须与 T 相同。 如果 UT,这是很简单的。 请注意,如果 U 不是 T,但是具有相同的大小和对齐方式,则基本上就像对不同类型的引用进行转换一样。 有关在这种情况下适用的限制的更多信息,请参见 mem::transmute

from_raw 的用户必须确保 T 的特定值仅被丢弃一次。

此函数不安全,因为使用不当可能会导致内存不安全,即使从未访问返回的 Arc<T> 也是如此。

Examples
use std::sync::Arc;

let x = Arc::new("hello".to_owned());
let x_ptr = Arc::into_raw(x);

unsafe {
    // 转换回 `Arc` 以防止泄漏。
    let x = Arc::from_raw(x_ptr);
    assert_eq!(&*x, "hello");

    // 进一步调用 `Arc::from_raw(x_ptr)` 将导致内存不安全。
}

// 当 `x` 超出上面的作用域时,其内存将被释放,所以 `x_ptr` 现在悬垂了!
Run
1.4.0 · source

pub fn downgrade(this: &Self) -> Weak<T>

创建一个指向该分配的新 Weak 指针。

Examples
use std::sync::Arc;

let five = Arc::new(5);

let weak_five = Arc::downgrade(&five);
Run
1.15.0 · source

pub fn weak_count(this: &Self) -> usize

获取指向该分配的 Weak 指针的数量。

Safety

此方法本身是安全的,但正确使用它需要格外小心。 另一个线程可以随时更改弱引用计数,包括潜在地在调用此方法与对结果进行操作之间。

Examples
use std::sync::Arc;

let five = Arc::new(5);
let _weak_five = Arc::downgrade(&five);

// 此断言是确定性的,因为我们尚未在线程之间共享 `Arc` 或 `Weak`。
assert_eq!(1, Arc::weak_count(&five));
Run
1.15.0 · source

pub fn strong_count(this: &Self) -> usize

获取指向此分配的强 (Arc) 指针的数量。

Safety

此方法本身是安全的,但正确使用它需要格外小心。 另一个线程可以随时更改强引用计数,包括潜在地在调用此方法与对结果进行操作之间。

Examples
use std::sync::Arc;

let five = Arc::new(5);
let _also_five = Arc::clone(&five);

// 此断言是确定性的,因为我们尚未在线程之间共享 `Arc`。
assert_eq!(2, Arc::strong_count(&five));
Run
1.51.0 · source

pub unsafe fn increment_strong_count(ptr: *const T)

与提供的指针关联的 Arc<T> 上的强引用计数加 1。

Safety

指针必须已经通过 Arc::into_raw 获得,并且关联的 Arc 实例必须有效 (即 在此方法的持续时间内,强引用计数必须至少为 1)。

Examples
use std::sync::Arc;

let five = Arc::new(5);

unsafe {
    let ptr = Arc::into_raw(five);
    Arc::increment_strong_count(ptr);

    // 此断言是确定性的,因为我们尚未在线程之间共享 `Arc`。
    let five = Arc::from_raw(ptr);
    assert_eq!(2, Arc::strong_count(&five));
}
Run
1.51.0 · source

pub unsafe fn decrement_strong_count(ptr: *const T)

将与提供的指针关联的 Arc<T> 上的强引用计数减 1。

Safety

指针必须已经通过 Arc::into_raw 获得,并且关联的 Arc 实例必须有效 (即 调用此方法时,强引用计数必须至少为 1)。 此方法可用于释放最终的 Arc 和后备存储,但不应在最终的 Arc 释放后调用。

Examples
use std::sync::Arc;

let five = Arc::new(5);

unsafe {
    let ptr = Arc::into_raw(five);
    Arc::increment_strong_count(ptr);

    // 这些断言是确定性的,因为我们尚未在线程之间共享 `Arc`。
    let five = Arc::from_raw(ptr);
    assert_eq!(2, Arc::strong_count(&five));
    Arc::decrement_strong_count(ptr);
    assert_eq!(1, Arc::strong_count(&five));
}
Run
1.17.0 · source

pub fn ptr_eq(this: &Self, other: &Self) -> bool

如果两个 Arc 以类似于 ptr::eq 的方式指向相同的分配,则返回 true。 比较 dyn Trait 指针时的注意事项,请参见 that function

Examples
use std::sync::Arc;

let five = Arc::new(5);
let same_five = Arc::clone(&five);
let other_five = Arc::new(5);

assert!(Arc::ptr_eq(&five, &same_five));
assert!(!Arc::ptr_eq(&five, &other_five));
Run
source§

impl<T: Clone> Arc<T>

1.4.0 · source

pub fn make_mut(this: &mut Self) -> &mut T

对给定的 Arc 进行可变引用。

如果有其他 Arc 指针指向同一分配,则 make_mut 会将内部值 clone 到新分配以确保唯一的所有权。 这也称为写时克隆。

但是,如果没有其他 Arc 指针指向这个分配,而是一些 Weak 指针,那么 Weak 指针将被分离,内部值不会被克隆。

另请参见 get_mut,它将失败而不是克隆内部值或分离 Weak 指针。

Examples
use std::sync::Arc;

let mut data = Arc::new(5);

*Arc::make_mut(&mut data) += 1;         // 不会克隆任何东西
let mut other_data = Arc::clone(&data); // 不会克隆内部数据
*Arc::make_mut(&mut data) += 1;         // 克隆内部数据
*Arc::make_mut(&mut data) += 1;         // 不会克隆任何东西
*Arc::make_mut(&mut other_data) *= 2;   // 不会克隆任何东西

// 现在,`data` 和 `other_data` 指向不同的分配。
assert_eq!(*data, 8);
assert_eq!(*other_data, 12);
Run

Weak 指针将被分离:

use std::sync::Arc;

let mut data = Arc::new(75);
let weak = Arc::downgrade(&data);

assert!(75 == *data);
assert!(75 == *weak.upgrade().unwrap());

*Arc::make_mut(&mut data) += 1;

assert!(76 == *data);
assert!(weak.upgrade().is_none());
Run
source

pub fn unwrap_or_clone(this: Self) -> T

🔬This is a nightly-only experimental API. (arc_unwrap_or_clone #93610)

如果我们有 T 的唯一引用,那就打开它。否则,克隆 T 并返回克隆。

假设 arc_tArc<T> 类型,这个函数在功能上等同于 (*arc_t).clone(),但会尽可能避免克隆内部值。

Examples
#![feature(arc_unwrap_or_clone)]
let inner = String::from("test");
let ptr = inner.as_ptr();

let arc = Arc::new(inner);
let inner = Arc::unwrap_or_clone(arc);
// 内部值没有被克隆
assert!(ptr::eq(ptr, inner.as_ptr()));

let arc = Arc::new(inner);
let arc2 = arc.clone();
let inner = Arc::unwrap_or_clone(arc);
// 因为有两个引用,我们不得不克隆内部值。
assert!(!ptr::eq(ptr, inner.as_ptr()));
// `arc2` 是最后一个引用,所以当我们展开它时,我们会得到原来的 `String`。
let inner = Arc::unwrap_or_clone(arc2);
assert!(ptr::eq(ptr, inner.as_ptr()));
Run
source§

impl<T: ?Sized> Arc<T>

1.4.0 · source

pub fn get_mut(this: &mut Self) -> Option<&mut T>

如果没有其他 ArcWeak 指向相同分配的指针,则返回给定 Arc 的可变引用。

否则返回 None,因为更改共享值并不安全。

另见 make_mut,当有其他 Arc 指针时,它将 clone 内部值。

Examples
use std::sync::Arc;

let mut x = Arc::new(3);
*Arc::get_mut(&mut x).unwrap() = 4;
assert_eq!(*x, 4);

let _y = Arc::clone(&x);
assert!(Arc::get_mut(&mut x).is_none());
Run
source

pub unsafe fn get_mut_unchecked(this: &mut Self) -> &mut T

🔬This is a nightly-only experimental API. (get_mut_unchecked #63292)

将变量引用返回给定的 Arc,而不进行任何检查。

另请参见 get_mut,它是安全的并且进行适当的检查。

Safety

如果存在指向同一分配的任何其他 ArcWeak 指针,则在返回的借用期间,它们不得被解引用或具有活动借用,并且它们的内部类型必须与此 Rc 的内部类型完全相同 (包括生命周)。 如果不存在这样的指针 (例如紧接在 Arc::new 之后),则情况很简单。

Examples
#![feature(get_mut_unchecked)]

use std::sync::Arc;

let mut x = Arc::new(String::new());
unsafe {
    Arc::get_mut_unchecked(&mut x).push_str("foo")
}
assert_eq!(*x, "foo");
Run

指向同一分配的其他 Arc 指针必须指向同一类型。

#![feature(get_mut_unchecked)]

use std::sync::Arc;

let x: Arc<str> = Arc::from("Hello, world!");
let mut y: Arc<[u8]> = x.clone().into();
unsafe {
    // 这是未定义的行为,因为 x 的内部类型是 str,而不是 [u8]
    Arc::get_mut_unchecked(&mut y).fill(0xff); // 0xff 在 UTF-8 中无效
}
println!("{}", &*x); // str 中的 UTF-8 无效
Run

指向同一分配的其他 Arc 指针必须指向完全相同的类型,包括生命周期。

#![feature(get_mut_unchecked)]

use std::sync::Arc;

let x: Arc<&str> = Arc::new("Hello, world!");
{
    let s = String::from("Oh, no!");
    let mut y: Arc<&str> = x.clone().into();
    unsafe {
        // 这是未定义的行为,因为 x 的内部类型是 &'long str,而不是 &'short str
        *Arc::get_mut_unchecked(&mut y) = &s;
    }
}
println!("{}", &*x); // Use-after-free
Run
source§

impl Arc<dyn Any + Send + Sync>

1.29.0 · source

pub fn downcast<T>(self) -> Result<Arc<T>, Self>where T: Any + Send + Sync,

尝试将 Arc<dyn Any + Send + Sync> 转换为具体类型。

Examples
use std::any::Any;
use std::sync::Arc;

fn print_if_string(value: Arc<dyn Any + Send + Sync>) {
    if let Ok(string) = value.downcast::<String>() {
        println!("String ({}): {}", string.len(), string);
    }
}

let my_string = "Hello World".to_string();
print_if_string(Arc::new(my_string));
print_if_string(Arc::new(0i8));
Run
source

pub unsafe fn downcast_unchecked<T>(self) -> Arc<T>where T: Any + Send + Sync,

🔬This is a nightly-only experimental API. (downcast_unchecked #90850)

Arc<dyn Any + Send + Sync> 向下转换为具体类型。

有关安全的替代方案,请参见 downcast

Examples
#![feature(downcast_unchecked)]

use std::any::Any;
use std::sync::Arc;

let x: Arc<dyn Any + Send + Sync> = Arc::new(1_usize);

unsafe {
    assert_eq!(*x.downcast_unchecked::<usize>(), 1);
}
Run
Safety

包含的值必须是 T 类型。 使用不正确的类型调用此方法是 未定义的行为

Trait Implementations§

1.5.0 · source§

impl<T: ?Sized> AsRef<T> for Arc<T>

source§

fn as_ref(&self) -> &T

将此类型转换为 (通常是推断的) 输入类型的共享引用。
source§

impl<T: ?Sized> Borrow<T> for Arc<T>

source§

fn borrow(&self) -> &T

从拥有的值中一成不变地借用。 Read more
source§

impl<T: ?Sized> Clone for Arc<T>

source§

fn clone(&self) -> Arc<T>

克隆 Arc 指针。

这将创建另一个指向相同分配的指针,从而增加了强引用计数。

Examples
use std::sync::Arc;

let five = Arc::new(5);

let _ = Arc::clone(&five);
Run
source§

fn clone_from(&mut self, source: &Self)

source 执行复制分配。 Read more
source§

impl<T: ?Sized + Debug> Debug for Arc<T>

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

使用给定的格式化程序格式化该值。 Read more
source§

impl<T: Default> Default for Arc<T>

source§

fn default() -> Arc<T>

TDefault 值创建一个新的 Arc<T>

Examples
use std::sync::Arc;

let x: Arc<i32> = Default::default();
assert_eq!(*x, 0);
Run
source§

impl<T: ?Sized> Deref for Arc<T>

§

type Target = T

解引用后的结果类型。
source§

fn deref(&self) -> &T

解引用值。
source§

impl<T: ?Sized + Display> Display for Arc<T>

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

使用给定的格式化程序格式化该值。 Read more
source§

impl<T: ?Sized> Drop for Arc<T>

source§

fn drop(&mut self)

丢弃 Arc

这将减少强引用计数。 如果强引用计数达到零,那么唯一的其他引用 (如果有) 是 Weak,因此我们将 drop 作为内部值。

Examples
use std::sync::Arc;

struct Foo;

impl Drop for Foo {
    fn drop(&mut self) {
        println!("dropped!");
    }
}

let foo  = Arc::new(Foo);
let foo2 = Arc::clone(&foo);

drop(foo);    // 不打印任何东西
drop(foo2);   // 打印 "dropped!"
Run
1.52.0 · source§

impl<T: Error + ?Sized> Error for Arc<T>

source§

fn description(&self) -> &str

👎Deprecated since 1.42.0: use the Display impl or to_string()
source§

fn cause(&self) -> Option<&dyn Error>

👎Deprecated since 1.33.0: replaced by Error::source, which can support downcasting
source§

fn source(&self) -> Option<&(dyn Error + 'static)>

此错误的下级来源 (如果有)。 Read more
source§

fn provide<'a>(&'a self, req: &mut Demand<'a>)

🔬This is a nightly-only experimental API. (error_generic_member_access #99301)
提供对用于错误报告的上下文的基于类型的访问。 Read more
1.21.0 · source§

impl<T: Clone> From<&[T]> for Arc<[T]>

source§

fn from(v: &[T]) -> Arc<[T]>

分配一个引用计数的切片,并通过克隆 v 的项来填充它。

Example
let original: &[i32] = &[1, 2, 3];
let shared: Arc<[i32]> = Arc::from(original);
assert_eq!(&[1, 2, 3], &shared[..]);
Run
1.24.0 · source§

impl From<&CStr> for Arc<CStr>

source§

fn from(s: &CStr) -> Arc<CStr>

通过将内容复制到新分配的 Arc 中,将 &CStr 转换为 Arc<CStr>

1.21.0 · source§

impl From<&str> for Arc<str>

source§

fn from(v: &str) -> Arc<str>

分配一个引用计数的 str 并将 v 复制到其中。

Example
let shared: Arc<str> = Arc::from("eggplant");
assert_eq!("eggplant", &shared[..]);
Run
1.51.0 · source§

impl<W: Wake + Send + Sync + 'static> From<Arc<W>> for RawWaker

source§

fn from(waker: Arc<W>) -> RawWaker

使用 Wake 类型作为 RawWaker

此转换不使用堆分配或原子操作。

1.51.0 · source§

impl<W: Wake + Send + Sync + 'static> From<Arc<W>> for Waker

source§

fn from(waker: Arc<W>) -> Waker

使用 Wake 类型作为 Waker

此转换不使用堆分配或原子操作。

1.62.0 · source§

impl From<Arc<str>> for Arc<[u8]>

source§

fn from(rc: Arc<str>) -> Self

将原子引用计数的字符串切片转换为字节切片。

Example
let string: Arc<str> = Arc::from("eggplant");
let bytes: Arc<[u8]> = Arc::from(string);
assert_eq!("eggplant".as_bytes(), bytes.as_ref());
Run
1.21.0 · source§

impl<T: ?Sized> From<Box<T, Global>> for Arc<T>

source§

fn from(v: Box<T>) -> Arc<T>

将 boxed 对象移动到新的引用计数分配。

Example
let unique: Box<str> = Box::from("eggplant");
let shared: Arc<str> = Arc::from(unique);
assert_eq!("eggplant", &shared[..]);
Run
1.24.0 · source§

impl From<CString> for Arc<CStr>

source§

fn from(s: CString) -> Arc<CStr>

通过将 CString 数据移动到新的 Arc 缓冲区中,将 CString 转换为 Arc<CStr>

1.45.0 · source§

impl<'a, B> From<Cow<'a, B>> for Arc<B>where B: ToOwned + ?Sized, Arc<B>: From<&'a B> + From<B::Owned>,

source§

fn from(cow: Cow<'a, B>) -> Arc<B>

通过复制其内容,从写时克隆指针创建一个原子引用计数指针。

Example
let cow: Cow<'_, str> = Cow::Borrowed("eggplant");
let shared: Arc<str> = Arc::from(cow);
assert_eq!("eggplant", &shared[..]);
Run
1.21.0 · source§

impl From<String> for Arc<str>

source§

fn from(v: String) -> Arc<str>

分配一个引用计数的 str 并将 v 复制到其中。

Example
let unique: String = "eggplant".to_owned();
let shared: Arc<str> = Arc::from(unique);
assert_eq!("eggplant", &shared[..]);
Run
1.6.0 · source§

impl<T> From<T> for Arc<T>

source§

fn from(t: T) -> Self

T 转换为 Arc<T>

转换将值移动到新分配的 Arc 中。 相当于调用 Arc::new(t)

Example
let x = 5;
let arc = Arc::new(5);

assert_eq!(Arc::from(x), arc);
Run
1.21.0 · source§

impl<T> From<Vec<T, Global>> for Arc<[T]>

source§

fn from(v: Vec<T>) -> Arc<[T]>

分配一个引用计数的切片,并将 v 的项移入其中。

Example
let unique: Vec<i32> = vec![1, 2, 3];
let shared: Arc<[i32]> = Arc::from(unique);
assert_eq!(&[1, 2, 3], &shared[..]);
Run
1.37.0 · source§

impl<T> FromIterator<T> for Arc<[T]>

source§

fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self

获取 Iterator 中的每个元素,并将其收集到 Arc<[T]> 中。

性能特点
一般情况

在一般情况下,首先要收集到 Vec<T> 中来收集到 Arc<[T]> 中。也就是说,编写以下内容时:

let evens: Arc<[u8]> = (0..10).filter(|&x| x % 2 == 0).collect();
Run

这就像我们写的那样:

let evens: Arc<[u8]> = (0..10).filter(|&x| x % 2 == 0)
    .collect::<Vec<_>>() // 第一组分配在此处发生。
    .into(); // `Arc<[T]>` 的第二个分配在此处进行。
Run

这将分配构造 Vec<T> 所需的次数,然后分配一次,以将 Vec<T> 转换为 Arc<[T]>

已知长度的迭代器

当您的 Iterator 实现 TrustedLen 且大小正确时,将为 Arc<[T]> 进行一次分配。例如:

let evens: Arc<[u8]> = (0..10).collect(); // 这里只进行一次分配。
Run
source§

impl<T: ?Sized + Hash> Hash for Arc<T>

source§

fn hash<H: Hasher>(&self, state: &mut H)

将该值输入给定的 HasherRead more
1.3.0 · source§

fn hash_slice<H>(data: &[Self], state: &mut H)where H: Hasher, Self: Sized,

将这种类型的切片送入给定的 Hasher 中。 Read more
source§

impl<T: ?Sized + Ord> Ord for Arc<T>

source§

fn cmp(&self, other: &Arc<T>) -> Ordering

两个 Arc 的比较。

通过调用 cmp() 的内部值来比较两者。

Examples
use std::sync::Arc;
use std::cmp::Ordering;

let five = Arc::new(5);

assert_eq!(Ordering::Less, five.cmp(&Arc::new(6)));
Run
1.21.0 · source§

fn max(self, other: Self) -> Selfwhere Self: Sized,

比较并返回两个值中的最大值。 Read more
1.21.0 · source§

fn min(self, other: Self) -> Selfwhere Self: Sized,

比较并返回两个值中的最小值。 Read more
1.50.0 · source§

fn clamp(self, min: Self, max: Self) -> Selfwhere Self: Sized + PartialOrd<Self>,

将值限制在某个时间间隔内。 Read more
source§

impl<T: ?Sized + PartialEq> PartialEq<Arc<T>> for Arc<T>

source§

fn eq(&self, other: &Arc<T>) -> bool

两个 Arc 的相等性。

即使两个 Arc 的内部值相等,即使它们存储在不同的分配中,它们也相等。

如果 T 还实现了 Eq (暗示相等的反射性),则指向同一分配的两个 Arc 总是相等的。

Examples
use std::sync::Arc;

let five = Arc::new(5);

assert!(five == Arc::new(5));
Run
source§

fn ne(&self, other: &Arc<T>) -> bool

两个 Arc 的不等式。

如果两个 Arc 的内部值不相等,则它们不相等。

如果 T 也实现了 Eq (暗示相等的,反射,性),则指向相同值的两个 Arc 总是相等的。

Examples
use std::sync::Arc;

let five = Arc::new(5);

assert!(five != Arc::new(6));
Run
source§

impl<T: ?Sized + PartialOrd> PartialOrd<Arc<T>> for Arc<T>

source§

fn partial_cmp(&self, other: &Arc<T>) -> Option<Ordering>

两个 Arc 的部分比较。

通过调用 partial_cmp() 的内部值来比较两者。

Examples
use std::sync::Arc;
use std::cmp::Ordering;

let five = Arc::new(5);

assert_eq!(Some(Ordering::Less), five.partial_cmp(&Arc::new(6)));
Run
source§

fn lt(&self, other: &Arc<T>) -> bool

小于两个 Arc 的比较。

通过调用 < 的内部值来比较两者。

Examples
use std::sync::Arc;

let five = Arc::new(5);

assert!(five < Arc::new(6));
Run
source§

fn le(&self, other: &Arc<T>) -> bool

两个 Arc 的小于或等于比较。

通过调用 <= 的内部值来比较两者。

Examples
use std::sync::Arc;

let five = Arc::new(5);

assert!(five <= Arc::new(5));
Run
source§

fn gt(&self, other: &Arc<T>) -> bool

大于两个 Arc 的比较。

通过调用 > 的内部值来比较两者。

Examples
use std::sync::Arc;

let five = Arc::new(5);

assert!(five > Arc::new(4));
Run
source§

fn ge(&self, other: &Arc<T>) -> bool

两个 Arc 的大于或等于比较。

通过调用 >= 的内部值来比较两者。

Examples
use std::sync::Arc;

let five = Arc::new(5);

assert!(five >= Arc::new(5));
Run
source§

impl<T: ?Sized> Pointer for Arc<T>

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

使用给定的格式化程序格式化该值。
1.43.0 · source§

impl<T, const N: usize> TryFrom<Arc<[T]>> for Arc<[T; N]>

§

type Error = Arc<[T]>

发生转换错误时返回的类型。
source§

fn try_from(boxed_slice: Arc<[T]>) -> Result<Self, Self::Error>

执行转换。
source§

impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<Arc<U>> for Arc<T>

source§

impl<T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<Arc<U>> for Arc<T>

source§

impl<T: ?Sized + Eq> Eq for Arc<T>

source§

impl<T: ?Sized + Sync + Send> Send for Arc<T>

source§

impl<T: ?Sized + Sync + Send> Sync for Arc<T>

1.33.0 · source§

impl<T: ?Sized> Unpin for Arc<T>

1.9.0 · source§

impl<T: RefUnwindSafe + ?Sized> UnwindSafe for Arc<T>

Auto Trait Implementations§

§

impl<T: ?Sized> RefUnwindSafe for Arc<T>where T: RefUnwindSafe,

Blanket Implementations§

source§

impl<T> Any for Twhere T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

获取 selfTypeIdRead more
source§

impl<T> Borrow<T> for Twhere T: ?Sized,

source§

fn borrow(&self) -> &T

从拥有的值中一成不变地借用。 Read more
source§

impl<T> BorrowMut<T> for Twhere T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

从拥有的值中借用。 Read more
source§

impl<T> From<!> for T

source§

fn from(t: !) -> T

从输入类型转换为此类型。
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

返回未更改的参数。

source§

impl<T, U> Into<U> for Twhere U: From<T>,

source§

fn into(self) -> U

调用 U::from(self)

也就是说,这种转换是 From<T> for U 实现选择执行的任何操作。

source§

impl<E> Provider for Ewhere E: Error + ?Sized,

source§

fn provide<'a>(&'a self, demand: &mut Demand<'a>)

🔬This is a nightly-only experimental API. (provide_any #96024)
数据提供者应实现此方法以提供他们能够通过使用 demand 提供的所有值。 Read more
source§

impl<T> ToOwned for Twhere T: Clone,

§

type Owned = T

获得所有权后的结果类型。
source§

fn to_owned(&self) -> T

从借用的数据创建拥有的数据,通常是通过克隆。 Read more
source§

fn clone_into(&self, target: &mut T)

使用借来的数据来替换拥有的数据,通常是通过克隆。 Read more
source§

impl<T> ToString for Twhere T: Display + ?Sized,

source§

default fn to_string(&self) -> String

将给定值转换为 StringRead more
source§

impl<T, U> TryFrom<U> for Twhere U: Into<T>,

§

type Error = Infallible

发生转换错误时返回的类型。
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

执行转换。
source§

impl<T, U> TryInto<U> for Twhere U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

发生转换错误时返回的类型。
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

执行转换。