前言

来自 《Rust Atomics and Locks》 的翻译文章,英文原文https://marabos.nl/atomics/preface.html在新窗口打开

Rust 在使系统编程更易于访问方面发挥了并将继续发挥重要作用。然而,诸如原子和内存顺序之类的低级并发主题仍然经常被认为是有些神秘的主题,最好留给极少数专家。

在过去几年从事基于 Rust 的实时控制系统和 Rust 标准库的工作时,我发现许多关于原子和相关主题的可用资源只涵盖了我正在寻找的一小部分信息。许多资源完全集中在 C 和 C++ 上,这很难与 Rust 的(内存和线程)安全和类型系统概念建立联系。涵盖抽象理论细节的资源,如 C++ 的内存模型,通常只能模糊地解释它与实际硬件的关系,如果有的话。有许多资源涵盖了实际硬件的每个细节,例如处理器指令和高速缓存一致性,但形成整体理解通常需要从许多不同的地方收集点点滴滴的信息。

本书试图将相关信息放在一个地方,将它们连接在一起,提供构建自己正确、安全且符合人体工程学的并发原语所需的一切,同时充分了解底层硬件和操作系统的作用,能够做出设计决策和基本的优化权衡。

本书适合谁

本书的主要读者是想要更多地了解低级并发的 Rust 开发人员。此外,本书也适合那些对 Rust 还不是很熟悉,但想从 Rust 的角度了解低级并发是什么样子的人。

假定您了解 Rust 的基础知识,安装了最新的 Rust 编译器,并且知道如何使用 cargo 编译和运行 Rust 代码。对并发性很重要的 Rust 概念在相关时进行了简要解释,因此无需事先了解 Rust 并发性。

章节概述

本书由十章组成。以下是每一章的预期内容,以及值得期待的内容:

第 1 章 — Rust 并发基础

本章介绍了我们在 Rust 中实现基本并发所需的所有工具和概念,例如线程、互斥锁、线程安全、共享和独占引用、内部可变性等,这些都是本书其余部分的基础。

对于熟悉这些概念的有经验的 Rust 程序员,本章可以作为快速复习。对于那些从其他语言了解这些概念但还不太熟悉 Rust 的人,本章将快速让您了解本书其余部分可能需要的任何 Rust 特定知识。

第 2 章 — 原子(Atomics)

在第二章中,我们将了解 Rust 的原子类型及其所有操作。我们从简单的加载和存储操作开始,逐步构建更高级的比较和交换循环,用几个真实世界的用例作为可用示例来探索每个新概念。

虽然内存顺序与每个原子操作相关,但该主题要留给下一章。本章只涉及宽松内存顺序的情况,这种情况比人们预期的要多。

第 3 章——内存顺序

在了解了各种原子操作以及如何使用它们之后,第三章介绍了本书最复杂的主题:内存顺序。

我们将探讨内存模型的工作原理、先行发生关系是什么以及如何创建它们、所有不同的内存顺序意味着什么,以及为什么顺序一致的排序可能无法解决所有问题。

第 4 章——构建我们自己的自旋锁

在学习了理论之后,我们将在接下来的三章中通过构建我们自己的几种常见并发原语的版本来将其付诸实践。这些章节的第一章很短,我们在其中实现了自旋锁。

我们将从一个非常小的版本开始,以实践释放和获取内存顺序,然后我们将探索 Rust 的安全概念,将其转变为符合人体工程学且难以滥用的 Rust 数据类型。

第 5 章——建立我们自己的通道

在第 5 章中,我们将从头开始实现一次性通道的一些变体,这是一种可用于将数据从一个线程发送到另一个线程的原语。

从一个非常小但完全是 unsafe 的版本开始,我们将通过多种方式设计一个安全的接口,同时考虑设计决策及其后果。

第 6 章——构建我们自己的“Arc”

在第 6 章中,我们将解决一个更具挑战性的内存顺序难题。我们将从头开始实现我们自己的原子引用计数版本。

添加对弱指针的支持并针对性能对其进行优化后,我们的最终版本实际上将与 Rust 的标准 std::sync::Arc 类型相同。

第 7 章 — 了解处理器

第 7 章深入探讨了所有底层细节。我们将探讨在处理器级别发生了什么,原子操作背后的汇编指令在两种最流行的处理器架构上是什么样子的,缓存是什么以及它如何影响我们代码的性能,我们将找出剩下的内容硬件级别的内存模型。

第 8 章 — 操作系统原语

在第 8 章中,我们承认有些事情没有操作系统内核的帮助是无法完成的,并了解了 Linux、macOS 和 Windows 上有哪些功能可用。

我们将讨论通过 POSIX 系统上的 pthreads 可用的并发原语,了解我们可以使用 Windows API 做什么,并了解 Linux futex 系统调用的作用。

第 9 章——构建我们自己的锁

使用我们在前几章中学到的知识,在第 9 章中,我们将从头开始构建互斥锁、条件变量和读写锁的多个实现。

对于其中的每一个,我们将从一个最小但完整的版本开始,然后我们将尝试以各种方式对其进行优化。使用一些简单的基准测试,我们会发现我们的优化尝试并不总能提高性能,同时我们讨论了各种设计权衡。

第 10 章——想法和灵感

最后一章确保你在读完本书后不会陷入一片空白,而是留下了想法和灵感,可以用你的新知识和技能来构建和探索事物,也许会开始一段激动人心的旅程,进一步深入低级并发。

代码示例

本书中的所有代码都是使用 Rust 1.66.0 编写和测试的,该版本于 2022 年 12 月 15 日发布。早期版本不包括本书中使用的所有功能。但是,更高版本应该可以正常工作。

为简洁起见,代码示例不包括 use 语句,除了第一次引入标准库中的新项目。为方便起见,可以使用以下序言导入编译本书中任何代码示例所需的一切:

#[allow(unused)]
use std::{
    cell::{Cell, RefCell, UnsafeCell},
    collections::VecDeque,
    marker::PhantomData,
    mem::{ManuallyDrop, MaybeUninit},
    ops::{Deref, DerefMut},
    ptr::NonNull,
    rc::Rc,
    sync::{*, atomic::{*, Ordering::*}},
    thread::{self, Thread},
};
上次更新: