Struct alloc::sync::Arc1.0.0[][src]

pub struct Arc<T: ?Sized> { /* fields omitted */ }
Expand description

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

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

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

线程安全

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

Arc<T> 只要 T 实现 SendSync,就将实现 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 都是指向相同内存位置的弧
Run

Deref behavior

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

use std::sync::Arc;

let my_arc = Arc::new(());
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

创建一个新的 Arc<T>

Examples

use std::sync::Arc;

let five = Arc::new(5);
Run
🔬 This is a nightly-only experimental API. (arc_new_cyclic #75861)

使用对自身的弱引用创建一个新的 Arc<T>。 在此函数返回之前尝试升级弱引用将得到 None 值。 但是,弱引用可以自由克隆并存储以备后用。

Examples

#![feature(arc_new_cyclic)]
#![allow(dead_code)]

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

struct Foo {
    me: Weak<Foo>,
}

let foo = Arc::new_cyclic(|me| Foo {
    me: me.clone(),
});
Run
🔬 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();

let five = unsafe {
    // 延迟初始化:
    Arc::get_mut_unchecked(&mut five).as_mut_ptr().write(5);

    five.assume_init()
};

assert_eq!(*five, 5)
Run
🔬 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

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

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

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

🔬 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
🔬 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()?;

let five = unsafe {
    // 延迟初始化:
    Arc::get_mut_unchecked(&mut five).as_mut_ptr().write(5);

    five.assume_init()
};

assert_eq!(*five, 5);
Run
🔬 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

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

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

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

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
🔬 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 values = unsafe {
    // 延迟初始化:
    Arc::get_mut_unchecked(&mut values)[0].as_mut_ptr().write(1);
    Arc::get_mut_unchecked(&mut values)[1].as_mut_ptr().write(2);
    Arc::get_mut_unchecked(&mut values)[2].as_mut_ptr().write(3);

    values.assume_init()
};

assert_eq!(*values, [1, 2, 3])
Run
🔬 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
🔬 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();

let five = unsafe {
    // 延迟初始化:
    Arc::get_mut_unchecked(&mut five).as_mut_ptr().write(5);

    five.assume_init()
};

assert_eq!(*five, 5)
Run
🔬 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 values = unsafe {
    // 延迟初始化:
    Arc::get_mut_unchecked(&mut values)[0].as_mut_ptr().write(1);
    Arc::get_mut_unchecked(&mut values)[1].as_mut_ptr().write(2);
    Arc::get_mut_unchecked(&mut values)[2].as_mut_ptr().write(3);

    values.assume_init()
};

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

消耗 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

为数据提供裸指针。

计数不会受到任何影响,并且不会消耗 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

从裸指针构造 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

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

Examples

use std::sync::Arc;

let five = Arc::new(5);

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

获取指向该分配的 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

获取指向此分配的强 (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

与提供的指针关联的 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

将与提供的指针关联的 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

如果两个 Arc 指向相同的分配 (类似于 ptr::eq),则返回 true

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

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

如果还有其他 ArcWeak 指针指向同一分配,则 make_mut 将创建一个新分配,并在内部值上调用 clone 以确保唯一的所有权。 这也称为写时克隆。

请注意,这与 Rc::make_mut 的行为不同,后者取消关联所有剩余的 Weak 指针。

另请参见 get_mut,它将失败而不是克隆。

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

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

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

另请参见 make_mut,当存在其他指针时,它将 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
🔬 This is a nightly-only experimental API. (get_mut_unchecked #63292)

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

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

Safety

在返回的借用期间,不得解引用其他指向相同分配的 ArcWeak 指针。

如果不存在这样的指针 (例如紧接在 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<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

Trait Implementations

执行转换。

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

克隆 Arc 指针。

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

Examples

use std::sync::Arc;

let five = Arc::new(5);

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

source 执行复制分配。 Read more

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

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

Examples

use std::sync::Arc;

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

解引用后的结果类型。

解引用值。

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

丢弃 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

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

Example

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

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

Example

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

使用 Wake 类型作为 Waker

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

使用 Wake 类型作为 RawWaker

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

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

Example

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

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

Example

let cow: Cow<str> = Cow::Borrowed("eggplant");
let shared: Arc<str> = Arc::from(cow);
assert_eq!("eggplant", &shared[..]);
Run

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

Example

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

T 转换为 Arc<T>

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

Example

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

assert_eq!(Arc::from(x), arc);
Run

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

Example

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

获取 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

将该值输入给定的 HasherRead more

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

两个 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

比较并返回两个值中的最大值。 Read more

比较并返回两个值中的最小值。 Read more

将值限制为一定的时间间隔。 Read more

两个 Arc 的相等性。

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

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

Examples

use std::sync::Arc;

let five = Arc::new(5);

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

两个 Arc 的不等式。

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

如果 T 还实现了 Eq (暗示相等性的反射性),则指向相同值的两个 `Arc’ 永远不会相等。

Examples

use std::sync::Arc;

let five = Arc::new(5);

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

两个 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

小于两个 Arc 的比较。

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

Examples

use std::sync::Arc;

let five = Arc::new(5);

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

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

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

Examples

use std::sync::Arc;

let five = Arc::new(5);

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

大于两个 Arc 的比较。

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

Examples

use std::sync::Arc;

let five = Arc::new(5);

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

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

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

Examples

use std::sync::Arc;

let five = Arc::new(5);

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

使用给定的格式化程序格式化该值。

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

执行转换。

Blanket Implementations

获取 selfTypeIdRead more

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

从拥有的值中借用。 Read more

执行转换。

执行转换。

执行转换。

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

通常通过克隆从借用数据中创建拥有的数据。 Read more

🔬 This is a nightly-only experimental API. (toowned_clone_into #41263)

recently added

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

将给定值转换为 StringRead more

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

执行转换。

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

执行转换。