无畏并发
安全且高效地处理并发编程,是 Rust 的另一个主要目标。并发编程(concurrent programming)指程序的不同部分彼此独立地执行,而并行编程(parallel programming)则指程序的不同部分同时执行。随着越来越多的计算机开始利用多处理器的优势,这两个概念正变得越来越重要。历史上,在这些场景中编程一直都很困难且容易出错。Rust 希望改变这一点。
起初,Rust 团队认为确保内存安全和防止并发问题是两个分别需要不同方法应对的挑战。随着时间的推移,团队发现所有权和类型系统是一系列解决内存安全和并发问题的强有力的工具!通过利用所有权和类型检查,在 Rust 中很多并发错误都是编译时错误,而非运行时错误。因此,相比花费大量时间尝试重现运行时并发 bug 出现的特定情况,不正确的代码会直接编译失败并提供解释问题的错误信息。因此,你可以在开发时修复代码,而不是在部署到生产环境后修复代码。我们给 Rust 的这一部分起了一个绰号无畏并发(fearless concurrency)。无畏并发令你的代码免于出现诡异的 bug 并可以轻松重构且无需担心会引入新的 bug。
注意:出于简洁的考虑,我们将很多问题归类为并发,而不是更准确的区分并发和/或并行。对于本章,当我们谈到并发时,请自行脑内替换为 并发和/或并行。在下一章中当区分二者更为重要时,我们会使用更准确的表述。
很多语言对它们所提供的并发问题解决方案都比较“教条”。例如,Erlang 拥有优雅的消息传递并发功能,但在线程间共享状态方面只有一些不那么直观的方式。对于高级语言来说,只支持可能解决方案中的一个子集,是合理的策略,因为高级语言通过放弃一部分控制权来换取抽象,并承诺由此带来的收益。然而,底层语言通常被期望在任何给定场景下都能提供性能最佳的解决方案,并且对硬件施加更少抽象。因此,Rust 提供了多种工具,让你能够按照最适合自身场景和需求的方式来建模问题。
如下是本章将要涉及到的内容:
- 如何创建线程来同时运行多段代码。
- 消息传递(message-passing)并发,其中信道(channel)在线程之间发送消息。
- 共享状态(shared-state)并发,其中多个线程可以访问同一份数据。
Sync和Sendtrait,它们将 Rust 的并发保证扩展到用户定义类型以及标准库提供的类型。