Rust从0到1-并发-可扩展性
有趣的是,Rust 语言自身提供的并发功能很少。我们之前讨论的几乎所有有关并发的内容,都是标准库的一部分,而不是 Rust 语言自身。也正因如此,我们对于并发处理的选择并不受限于标准库或语言自身,我们可以编写自己的并发功能或使用别人编写的。
不过,有两个并发概念是来自语言:std::marker 中的 Sync 和 Send trait。
通过 Send 允许在线程间转移所有权
实现了 Send trait 的类型,其所有权可以在线程间转移。几乎所有的 Rust 类型都实现了 Send ,不过有一些例外,包括 Rc
Rust 类型系统和 trait bound 确保了我们永远也不可能将线程不安全的 Rc
此外,任何完全由实现了 Send 的类型组成的类型会自动被标记 Send。几乎所有基本类型都实现了 Send,除了后面我们将会讨论的 raw pointer(原始指针或裸指针)。
通过 Sync 允许多线程访问
实现了 Sync trait 的类型可以安全的在多个线程中引用。从另一方面说,对于任意类型 T,如果 &T(T 的不可变引用)是 Send 的话 T 就是 Sync 的,也就是说如果其引用可以安全的发送到另一个线程,那么它就是 Sync 的,可以安全的在多个线程中并发访问。和 Send 类似,基本类型都是 Sync 的,完全由 Sync 的类型组成的类型也是 Sync 的。
智能指针 Rc
手动实现 Send 和 Sync 是不安全的
由于由 Send 和 Sync 的类型组成的类型,自动就是 Send 和 Sync (Rust会自动推断),我们并不需要手动实现 Send 和 Sync trait。因为他们是 marker trait(标记),甚至都不需要为它们实现方法。他们只是用于检查是否可用于并发。
手动实现这些 marker trait 涉及到编写不安全的 Rust 代码,在后面章节我们会介绍;目前,在创建新的用于并发的类型时,如果其不全部是由标记了 Send 和 Sync 的类型构成,需要多加小心,确保其是并发安全的。如果大家比较感兴趣,建议大家进一步阅读官方文档“The Rustonomicon ”。
总结
正如前面提到的,因为 Rust 本身提供了很少的处理并发的功能,有很多的并发方案都是由社区共享的 crates 实现,他们发展的比标准库更快;我们可以在网上搜索当前最好的用于处理多线程场景的 crates。
Rust 标准库提供了用于消息传递的 channel,和像 Mutex
接下来,我们将讨论当 Rust 程序规模变得更大时,对于问题建模和结构组织的习惯做法,以及这些与面向对象编程(Object Oriented Programming)概念的联系。