#hazard-pointers #pointers #hazard #atomic #thread-safe #data-structures #atomic-box

无 std atom_box

使用危害指针的安全、惯用的 Rust 实现 Atomic Box

4 个版本

0.2.0 2023年11月8日
0.1.2 2021年10月28日
0.1.1 2021年10月26日
0.1.0 2021年10月24日

并发 中排名第 552

每月下载量 35

MIT/Apache

62KB
932

Atom Box

Atom Box 提供了一个原子盒实现,其中盒拥有包含的值及其底层分配。因此,当没有任何线程访问它时,它将负责释放内存。

在底层,Atom Box 是 'Rust 中危害指针的安全实现'。

该项目一直旨在为多线程并发无锁数据结构中的安全内存回收提供安全且惯用的 Rust API。

讨论

在没有垃圾回收器的语言中构建无锁数据结构的一个困难是安全地回收分配的内存。例如,如果一个线程原子地加载一个指针,另一个线程随后交换了指针,我们需要一种机制来确定第一个线程何时不再访问该指针,我们可以回收底层内存。一个解决方案是使用基于纪元的内存回收,例如 Crossbeam 提供的。另一种方法是使用危害指针,这是在此 crate 中使用的实现。

许多使用此 crate 的用户可以在不了解底层机制的情况下使用 AtomBox。然而,在选择使用此特定实现时,应考虑以下一些重要因素

  • 每次加载都需要获取一个危害指针。这是一个线性于线程数和活动 AtomBox 数量的操作。
  • 危害指针本身及其尚未回收的已退役项目都有内存开销。
  • 危险指针仅在域被丢弃时才会被释放。对于默认共享域,它是静态分配的,因此永远不会被丢弃。如果这种行为不受欢迎,可以使用自定义域来确保危险指针实际上被回收。或者,您可以提出一个API问题,以便在不使用的危险指针可以被丢弃的情况下。

有关更详细的讨论,请参阅以下内容。

危险指针

危险指针提供了一种安全的内存回收方法。它保护对象在由一个或多个线程访问时不会被回收,但在访问时允许对象并发地被删除。

危险指针是单写多读指针,一次最多只能被一个线程拥有。为了保护对象A在使用时不会被回收,线程X将其拥有的一个危险指针P设置为A的地址。如果P在A被删除之前设置为&A(即它变得不可达),则只要P继续持有&A的值,A就不会被回收。

内存使用

  • 库元数据的尺寸与使用危险指针的线程数量线性相关,假设每个线程有固定数量的危险指针,这是典型的。
  • 退役但尚未回收的对象数量通常与危险指针的数量线性相关,通常与使用危险指针的线程数量线性相关。

替代安全回收方法

  • 锁定(互斥或共享)
    • 优点:简单易懂。
    • 缺点:序列化,高读者开销,高竞争,死锁。
    • 何时使用:当速度和竞争不是关键因素,且避免死锁简单时。
  • 引用计数(std::sync::Arc
    • 优点:自动回收,线程匿名,独立于线程本地数据支持,免疫于死锁。
    • 缺点:高读者(和写者)开销,高读者(和写者)竞争。
    • 何时使用:当缺乏线程本地支持且死锁可能成为问题,或需要自动回收时。
  • 读-拷贝-更新(RCU)
    • 优点:简单、快速、可扩展。
    • 缺点:对阻塞敏感。
    • 何时使用:当速度和可扩展性很重要,且对象在阻塞时不需要被保护。

贡献

欢迎贡献!请确保您只提交您编写的代码,或者您有权限分享。

除非您明确声明,否则任何有意提交以包含在Atom Box中的贡献,将按照MIT许可,不附带任何额外的条款或条件。

请随时通过pull请求记录问题和提出更改。

在提出pull请求之前,请确保您已运行以下命令。

cargo fmt
cargo clippy
cargo test

此外,如果您的任何更改引入了新的原子加载或非安全代码,请确保您已运行Loom和Miri测试(见下文)。

运行Loom测试

Atom Box设计用于并发代码,其中线程可以以多种方式交错,这可能会非常难以测试所有不同的交错方式。然而,有一个出色的rust工具Loom专门用于测试并发代码。在提交任何贡献之后,请确保您已运行loom测试。此外,您可以随时为loom测试做出贡献。要运行当前的loom测试套件,请运行

RUSTFLAGS="--cfg loom" cargo test --test concurrency_tests --release

运行Miri

为了验证对非安全代码的任何更改,请确保您运行Miri。这是一个用于检查非安全代码有效性的验证工具。您需要切换到nightly工具链。然后,您需要按照仓库中的说明安装Miri。

为了验证您的代码,请运行以下命令

RUST_BACKTRACE=1 MIRIFLAGS="-Zmiri-ignore-leaks -Zmiri-disable-isolation" cargo miri test

行为准则

我们遵循Rust行为准则

目前,审核团队仅由John Bell组成。我们欢迎更多成员加入:如果您想加入审核团队,请联系John Bell。

许可证

该项目遵循MIT许可证

参考

依赖关系

~0–26MB
~328K SLoC