Sync trait的std文档

Sync trait的std文档

https://doc.rust-lang.org/std/marker/trait.Sync.html

pub unsafe auto trait Sync { }

可以在线程之间安全共享引用的类型。

当编译器确定适当时,会自动实现此 trait。

精确的定义是:当且仅当 &TSend 时,类型 T 才是 Sync。 换句话说,如果在线程之间传递 &T 引用时没有 未定义的行为 (包括数据竞争) 的可能性。

正如人们所料,像 u8f64 这样的原始类型都是 Sync,包含它们的简单聚合类型也是如此,比如元组、结构体和枚举。 基本 Sync 类型的更多示例包括不可变类型 (例如 &T) 以及具有简单继承的可变性的类型,例如 BoxVec 和大多数其他集合类型。

(泛型参数必须为 Sync,容器才能 [Sync]。)

该定义的一个令人惊讶的结果是 &mut TSync (如果 TSync),即使看起来可能提供了不同步的可变的。 诀窍是,共享引用 (即 & &mut T) 后面的可变引用将变为只读,就好像它是 & &T 一样。 因此,没有数据竞争的风险。

不是 Sync 的类型是具有非线程安全形式的 “内部可变性” 的类型,例如 CellRefCell。 这些类型甚至允许通过不可变,共享引用来更改其内容。 例如,Cell 上的 set 方法采用 &self,因此它仅需要共享的引用 &Cell。 该方法不执行同步,因此 Cell 不能为 Sync

另一个非 Sync 类型的例子是引用计数指针 Rc。 给定任何引用 &Rc,您可以克隆新的 Rc,以非原子方式修改引用计数。

对于确实需要线程安全的内部可变性的情况,Rust 提供 原子数据类型 以及通过 sync::Mutexsync::RwLock 进行的显式锁定。 这些类型可确保任何可变的都不会引起数据竞争,因此类型为 Sync。 同样,sync::Arc 提供了 Rc 的线程安全模拟。

任何具有内部可变性的类型还必须在 value(s) 周围使用 cell::UnsafeCell 包装器,该包装器可以通过共享的引用进行更改。 未定义的行为 无法做到这一点。 例如,从 &T&mut Ttransmute 无效。

有关 Sync 的更多详细信息,请参见 the Nomicon