55 个版本
0.12.3 | 2024 年 5 月 24 日 |
---|---|
0.12.1 | 2022 年 5 月 31 日 |
0.12.0 | 2022 年 1 月 28 日 |
0.11.2 | 2021 年 8 月 27 日 |
0.2.7 | 2016 年 7 月 28 日 |
#1 in 并发
12,486,159 每月下载量
用于 29,337 个 Crates(2,676 个直接使用)
420KB
8K SLoC
parking_lot
此库提供了比 Rust 标准库中的更小、更快、更灵活的 Mutex
、RwLock
、Condvar
和 Once
实现,以及支持递归加锁的 ReentrantMutex
类型。它还公开了一个低级 API,用于创建自己的高效同步原语。
在 x86_64 Linux 上进行测试时,发现当无竞争时,parking_lot::Mutex
比标准库中的 std::sync::Mutex
快 1.5 倍,而在多个线程竞争时则快 5 倍。对于 RwLock
的数值取决于读者和写线程的数量,但几乎总是比标准库中的 RwLock
快,在某些情况下甚至快 50 倍。
特性
此库提供的原语与 Rust 标准库中的原语相比具有几个优势
Mutex
和Once
仅需 1 字节存储空间,而Condvar
和RwLock
仅需 1 个字节的存储空间。另一方面,在某些平台(如 macOS 和其他一些平台)上,标准库原语需要动态分配的Box
来持有特定于操作系统的同步原语。特别是Mutex
的小尺寸特别鼓励使用细粒度锁来提高并行性。- 无竞争锁的获取和释放通过快速的内联路径完成,这些路径仅需要一次原子操作。
- 微竞争(具有短关键区的竞争锁)通过在尝试获取锁时旋转几次来有效地处理。
- 锁是自适应的,在几次自旋尝试失败后,会挂起一个线程。这使得锁适用于长和短的关键部分。
Condvar
、RwLock
和Once
在 Windows XP 上运行,与那些类型的标准库版本不同。RwLock
利用支持该功能的处理器的硬件锁消除,这可以在许多读者的情况下带来巨大的性能提升。这必须通过hardware-lock-elision
功能来启用。RwLock
使用任务公平锁策略,这避免了读者和写者的饥饿,而标准库版本则没有任何保证。Condvar
保证不会产生虚假唤醒。只有在超时或被通知唤醒时,线程才会被唤醒。Condvar::notify_all
只会唤醒一个线程,并将其余的线程重新排队等待相关的Mutex
。这避免了所有线程同时尝试获取锁的雷鸣 herd 问题。RwLock
支持将写锁原子降级为读锁。Mutex
和RwLock
允许不带 RAII 守护对象进行原始解锁。Mutex<()>
和RwLock<()>
允许不带 RAII 守护对象进行原始锁定。Mutex
和RwLock
支持最终公平性,这允许它们在平均情况下公平,而不牺牲性能。- 支持递归锁定的
ReentrantMutex
类型。 - 一个实验性的死锁检测器,适用于
Mutex
、RwLock
和ReentrantMutex
。默认情况下,此功能是禁用的,可以通过deadlock_detection
功能启用。 RwLock
支持将“可升级”的读锁原子升级为写锁。- 可选支持 serde。通过
serde
功能启用。注意!此支持仅适用于Mutex
、ReentrantMutex
和RwLock
;Condvar
和Once
目前不支持。 - 当启用
send_guard
功能时,锁守护者可以发送到其他线程。
停车场
为了保持这些原语的大小,所有的线程排队和挂起功能都卸载到 停车场。这个想法基于 Webkit WTF::ParkingLot
类,该类本质上是一个哈希表映射,将锁地址映射到挂起的(休眠的)线程队列。Webkit 停车场本身受到了 Linux futexes 的启发,但它更强大,因为它允许在持有队列锁的同时调用回调。
夜间版与稳定版
在稳定版 Rust 上使用此库时有一些限制。
wasm32-unknown-unknown
目标仅在夜间构建版本中完全支持,需要在RUSTFLAGS
中添加-C target-feature=+atomics
,并通过传递给 cargo 的-Zbuild-std=panic_abort,std
实现。在稳定版本中,parking_lot 将大致正常工作,唯一的区别是如果遇到死锁,它将触发 panic 而不是无限期地阻塞。只需确保不要在稳定版本上启用-C target-feature=+atomics
,因为这将允许 wasm 在多线程中运行,这将完全破坏 parking_lot 的并发保证。
要启用仅夜间构建的功能,您需要启用 Cargo 中的 nightly
功能(见下文)。
使用方法
将以下内容添加到您的 Cargo.toml
[dependencies]
parking_lot = "0.12"
要启用仅夜间构建的功能,将以下内容添加到您的 Cargo.toml
[dependencies]
parking_lot = { version = "0.12", features = ["nightly"] }
可以通过启用 deadlock_detection
Cargo 功能来启用实验性的死锁检测器。
要允许将 MutexGuard
和 RwLock*Guard
发送到其他线程,请启用 send_guard
选项。
请注意,deadlock_detection
和 send_guard
功能不兼容,不能同时使用。
可以通过启用 hardware-lock-elision
功能来启用对 x86 的硬件锁消除支持。由于使用了内联汇编,这需要 Rust 1.59。
核心 parking_lot API 由 parking_lot_core
crate 提供。它独立于 parking_lot
crate 中的同步原语,以便核心 API 的更改不会对 parking_lot
的用户造成破坏性更改。
最低 Rust 版本
当前所需的最低 Rust 版本是 1.56。任何对此的更改都视为破坏性更改,并将需要主要版本号的升级。
许可
以下任一许可下提供
- Apache License,版本 2.0,(LICENSE-APACHE 或 https://www.apache.org/licenses/LICENSE-2.0)
- MIT 许可证 (LICENSE-MIT 或 https://opensource.org/licenses/MIT)
任选其一。
贡献
除非您明确声明,否则任何有意提交以包含在您的工作中的贡献,根据 Apache-2.0 许可证的定义,应按照上述方式双许可,不附加任何其他条款或条件。
依赖项
~0–6MB
~22K SLoC