可扩展并发与Sync
和Send
性状
有趣的是,Rust 语言的并发功能非常少。几乎 到目前为止,我们在本章中讨论的每个并发功能都是 是标准库的一部分,而不是语言的一部分。您的处理选项 并发性不限于语言或标准库;您可以 编写您自己的并发功能或使用其他人编写的功能。
但是,该语言中嵌入了两个并发概念:std::marker
性状Sync
和Send
.
允许在线程之间转移所有权Send
这Send
marker trait 表示
实施Send
可以在线程之间传输。几乎所有 Rust 类型
是Send
,但也有一些例外,包括Rc<T>
:这不能是Send
因为如果您克隆了Rc<T>
值并尝试转让所有权
克隆到另一个线程时,两个线程都可能会更新引用计数
同时。因此,Rc<T>
实现用于
您不想支付线程安全费用的单线程情况
性能损失。
因此,Rust 的类型系统和 trait 边界确保你永远不能
不小心发送了Rc<T>
值。当我们尝试做
this 在示例 16-14 中,我们得到了the trait Send is not implemented for Rc<Mutex<i32>>
.当我们切换到Arc<T>
,即Send
中,代码
编译。
完全由Send
types 会自动标记为Send
如
井。几乎所有原始类型都是Send
,除了原始指针之外,它
我们将在第 19 章中讨论。
允许从多个线程访问Sync
这Sync
marker trait 表示它对于实现Sync
从多个线程引用。换句话说,任何类型T
是Sync
如果&T
(对T
) 是Send
,表示引用
可以安全地发送到另一个线程。似Send
,基元类型为Sync
,以及完全由以下类型组成的类型Sync
也是Sync
.
智能指针Rc<T>
也不是Sync
原因与事实并非如此Send
.这RefCell<T>
type(我们在第 15 章中讨论过)和
亲属Cell<T>
类型不是Sync
.borrow 的实现
检查RefCell<T>
does 不是线程安全的。智能
指针Mutex<T>
是Sync
,并可用于与多个
线程,如“共享Mutex<T>
多个之间
线程”部分。
实施Send
和Sync
手动不安全
因为由Send
和Sync
traits 会自动
也Send
和Sync
,我们不必手动实现这些特征。如
marker trait 中,它们甚至没有任何方法可以实现。他们只是
对于强制实施与并发相关的不变量很有用。
手动实现这些 trait 涉及实现不安全的 Rust 代码。
我们将在第 19 章讨论使用不安全的 Rust 代码;目前,重要的
信息是构建新的 concurrent 类型,而不是由Send
和Sync
零件需要仔细考虑以维护安全保证。“这
Rustonomicon“提供了有关这些保证以及如何
维护他们。
总结
这并不是您在本书中看到的最后一个并发:项目中的 第 20 章将在更现实的情况下使用本章中的概念 比这里讨论的较小示例。
如前所述,因为 Rust 处理并发的方式很少是 作为语言的一部分,许多并发解决方案都以 crate 的形式实现。 这些库比标准库发展得更快,因此请务必搜索 online 用于多线程中使用的当前最先进的 crate 情况。
Rust 标准库提供了消息传递和智能
指针类型,例如Mutex<T>
和Arc<T>
,可以安全使用
并发上下文。类型系统和借用检查器确保
使用这些解决方案的代码不会以数据争用或无效引用结束。
一旦你让你的代码开始编译,你就可以放心了,它会很高兴
在多个线程上运行,而不会出现
其他语言。并发编程不再是一个令人恐惧的概念:
勇往直前,让你的程序同时进行,无所畏惧!
接下来,我们将讨论对问题进行建模和构建解决方案的惯用方法 随着你的 Rust 程序变得更大。此外,我们将讨论 Rust 的惯用语 与您可能熟悉的面向对象编程相关的内容相关联。
本文档由官方文档翻译而来,如有差异请以官方英文文档(https://doc.rust-lang.org/)为准