集册 Rust 中文教程 Send 和 Sync

Send 和 Sync

欢马劈雪     最近更新时间:2020-08-04 05:37:59

157

std::marker 模块中,有两个 trait:SendSync,它们与多线程安全相关。

标记为 marker trait 的 trait,它实际就是一种约定,没有方法的定义,也没有关联元素(associated items)。仅仅是一种约定,实现了它的类型必须满足这种约定。一种类型是否加上这种约定,要么是编译器的行为,要么是人工手动的行为。

SendSync 在大部分情况下(针对 Rust 的基础类型和 std 中的大部分类型),会由编译器自动推导出来。对于不能由编译器自动推导出来的类型,要使它们具有 SendSync 的约定,可以由人手动实现。实现的时候,必须使用 unsafe 前缀,因为 Rust 默认不信任程序员,由程序员自己控制的东西,统统标记为 unsafe,出了问题(比如,把不是线程安全的对象加上 Sync 约定)由程序员自行负责。

它们的定义如下:

如果 T: Send,那么将 T 传到另一个线程中时(按值传送),不会导致数据竞争或其它不安全情况。

  1. Send 是对象可以安全发送到另一个执行体中;
  2. Send 使被发送对象可以和产生它的线程解耦,防止原线程将此资源释放后,在目标线程中使用出错(use after free)。

如果 T: Sync,那么将 &T 传到另一个线程中时,不会导致数据竞争或其它不安全情况。

  1. Sync 是可以被同时多个执行体访问而不出错;
  2. Sync 防止的是竞争;

推论:

  1. T: Sync 意味着 &T: Send
  2. Sync + Copy = Send
  3. T: Send 时,可推导出 &mut T: Send
  4. T: Sync 时,可推导出 &mut T: Sync
  5. &mut T: Send 时,不能推导出 T: Send

(注:T, &T, &mut TBox<T> 等都是不同的类型)

具体的类型:

展开阅读全文