Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

16.4 通过 Send 和 Sync trait 来扩展并发

16.4.1. SendSync trait

Rust 语言本身的并发特性较少,目前所提及的并发特性都来自于标准库,而不是语言本身。其实无需局限于标准库的开发,可以自己实现并发。

Rust 语言中有两个并发概念:

  • std::marker::Sync trait
  • std::marker::Send trait

这两个 trait 叫标记 trait(marker traits),因为它们没有定义任何方法,只供标记特性。

16.4.2. Send:允许线程间转移所有权

在上一篇文章 16.3. 共享状态的并发 我们曾尝试在跨线程的情况下传递 Rc<T>,失败了,失败原因就是没有实现 Send trait。

Rust 里几乎所有的类型都实现了 Send:几乎所有的基础类型都实现了 Send trait。但 Rc<T> 没有实现 Send,它只能用于单线程场景。

任何完全由 Send 类型组成的类型也被标记为 Send,相当于实现了 Send trait。

16.4.3. Sync:允许从多线程访问

实现 Sync trait 的类型可以安全地被多个线程引用。也就是说,如果 T 实现了 Sync trait,那么 &T 就实现了 Send trait。

基础类型都实现了 Sync,任何完全由 Sync 组成的类型也相当于实现了 Sync。但是 Rc<T> 不是 SyncRefCell<T>Cell<T> 家族也不是 Sync,但是 Mutex<T>Sync

16.4.4. 手动实现 SendSync 是不安全的

由于由 SendSync 部分组成的类型也自动具有 SendSync,因此我们不必手动实现这些 trait。作为标记 trait,它们甚至没有任何方法可以实现。它们只是用于强制执行与并发相关的不变量。

手动实现这些 trait 涉及编写不安全的 Rust 代码。我们将在以后的文章 19.1. 摆脱安全性限制的 unsafe Rust 讨论使用不安全的 Rust 代码(关于这部分也可以看 The Rustonomicon);目前,重要的一点是:在构建新的并发类型时,需要仔细考虑 SendSync 组成部分,以维护安全保证。

总之一句话:不要尝试手动实现 SendSync!!!