pub unsafe auto trait Sync { }
Expand description
可以在线程之间安全共享引用的类型。
当编译器确定适当时,会自动实现此 trait。
确切的定义是:当且仅当 &T
是 Send
时,类型 T
才是 Sync
。
换句话说,如果在线程之间传递 &T
引用时没有 未定义的行为 (包括数据竞争) 的可能性。
正如人们所料,像 u8
和 f64
这样的原始类型都是 Sync
,包含它们的简单聚合类型也是如此,比如元组、结构体和枚举。
基本 Sync
类型的更多示例包括不可变类型 (例如 &T
) 以及具有简单继承的可变性的类型,例如 Box<T>
,Vec<T>
和大多数其他集合类型。
(泛型参数必须为 Sync
,才能使其容器为 [Sync]。)
该定义的一个令人惊讶的结果是 &mut T
是 Sync
(如果 T
是 Sync
),即使看起来可能提供了不同步的可变的。
诀窍是,共享引用 (即 & &mut T
) 后面的可变引用将变为只读,就好像它是 & &T
一样。
因此,没有数据竞争的风险。
不是 Sync
的类型是具有非线程安全形式的 “内部可变性” 的类型,例如 Cell
和 RefCell
。
这些类型甚至允许通过不可变,共享引用来更改其内容。
例如,Cell<T>
上的 set
方法采用 &self
,因此它仅需要共享的引用 &Cell<T>
。
该方法不执行同步,因此 Cell
不能为 Sync
。
另一个非 Sync
类型的例子是引用计数指针 Rc
。
给定任何引用 &Rc<T>
,您可以克隆新的 Rc<T>
,以非原子方式修改引用计数。
对于确实需要线程安全的内部可变性的情况,Rust 提供 原子数据类型 以及通过 sync::Mutex
和 sync::RwLock
进行的显式锁定。
这些类型可确保任何可变的都不会引起数据竞争,因此类型为 Sync
。
同样,sync::Arc
提供了 Rc
的线程安全模拟。
任何具有内部可变性的类型还必须在值周围使用 cell::UnsafeCell
包装器,该包装器可以通过共享引用进行转变。
不这样做是 未定义的行为。
例如,从 &T
到 &mut T
的 transmute
无效。
有关 Sync
的更多详细信息,请参见 the Nomicon。
Implementors§
impl Sync for AtomicBool
impl Sync for AtomicI8
impl Sync for AtomicI16
impl Sync for AtomicI32
impl Sync for AtomicI64
impl Sync for AtomicIsize
impl Sync for AtomicU8
impl Sync for AtomicU16
impl Sync for AtomicU32
impl Sync for AtomicU64
impl Sync for AtomicUsize
impl Sync for Waker
impl<Dyn: ?Sized> Sync for DynMetadata<Dyn>
impl<T> !Sync for OnceCell<T>
impl<T> Sync for ChunksExactMut<'_, T>where T: Sync,
impl<T> Sync for ChunksMut<'_, T>where T: Sync,
impl<T> Sync for RChunksExactMut<'_, T>where T: Sync,
impl<T> Sync for RChunksMut<'_, T>where T: Sync,
impl<T> Sync for AtomicPtr<T>
impl<T: Sync> Sync for core::slice::Iter<'_, T>
impl<T: Sync> Sync for core::slice::IterMut<'_, T>
impl<T: ?Sized + Sync> Sync for SyncUnsafeCell<T>
impl<T: ?Sized> !Sync for *const T
impl<T: ?Sized> !Sync for *mut T
impl<T: ?Sized> !Sync for Cell<T>
impl<T: ?Sized> !Sync for RefCell<T>
impl<T: ?Sized> !Sync for UnsafeCell<T>
impl<T: ?Sized> !Sync for NonNull<T>
NonNull
指针不是 Sync
,因为它们引用的数据可能是别名。