5 个不稳定版本

0.2.1 2022年5月29日
0.2.0 2022年5月8日
0.1.1 2022年3月29日
0.1.0 2022年3月29日
0.0.0 2020年10月8日

#517并发

每月下载量 36

MIT 许可证

155KB
2.5K SLoC

usync

Crates.io Documentation MSRV: 1.59.0

此库提供了 MutexRwLockCondvarBarrierOnce 的实现,它们的大小为字大小,通常与 parking_lot 中的实现一样快。它还提供了一个支持递归加锁的 ReentrantMutex 类型。

功能

此库提供的原语与 Rust 标准库中的原语相比具有多个优势

  1. 所有类型只需要 1 个字的空间。另一方面,标准库中的原语需要动态分配的 Box 来持有特定于操作系统的同步原语。特别是 Mutex 的大小较小,这鼓励使用细粒度锁来增加并行性。
  2. 由于它们仅由一个原子变量组成,具有常量初始化器并且不需要析构函数,因此这些原语可以用作 static 全局变量。标准库中的原语需要动态初始化,因此需要使用 lazy_static! 惰性初始化。
  3. 无竞争锁的获取和释放通过快速内联路径完成,这些路径只需要一次原子操作。
  4. 微内容竞争(具有短暂临界区的竞争锁)通过在尝试获取锁时旋转几次来有效地处理。
  5. 锁是自适应的,在几次失败的旋转尝试后挂起线程。这使得锁适合长和短临界区。
  6. Condvar::notify_all 通常只会唤醒一个线程,并将其余线程重新排队以等待关联的 Mutex。这避免了所有线程同时尝试获取锁的暴风骤雨问题。
  7. MutexRwLock 允许在没有 RAII 保护对象的情况下进行原始解锁。
  8. Mutex<()>RwLock<()> 允许在不使用 RAII 保护对象的情况下进行原始锁定。
  9. 支持递归锁定的 ReentrantMutex 类型。
  10. 当启用 send_guard 功能时,锁保护可以被发送到其他线程。

用户空间队列

为了使这些原始数据类型保持字大小,它们的状态在计数器、线程队列以及两者的组合之间进行复用。这类似于 Windows 的 Slim Synchronization Primitives。不采用 Linux futex 或 parking_lot 中所见到的全局队列的外部锁定。这些队列都嵌入在每个原始数据类型中,并通过无锁操作进行交互,以降低最坏情况下的争用延迟。

不幸的是,由于需要处理与同步状态相关的队列,因此无法保证 Condvar 的“无虚假唤醒”,并且 RwLock 的极端只读工作流程无法使用优化的原子操作来提高吞吐量。尽管如此,这些性能限制在实践中并不重要,尤其是在其他缓存效果发挥作用时。另一方面,写入/独占重负载比现有解决方案具有更好的可扩展性,并且针对微争用进行了大量优化。

夜间与稳定版

在稳定版 Rust 上使用此库时有一些限制

  • 您必须使用 const_* 函数(例如 const_mutex(val))来静态初始化锁定原始数据类型。在稳定版 Rust 中,使用例如 Mutex::new(val) 还不起作用。

要启用夜间专属功能,您需要在 Cargo 中启用 nightly 功能(见下文)。

使用方法

将此添加到您的 Cargo.toml

[dependencies]
usync = "0.2.1"

要启用夜间专属功能,请将此添加到您的 Cargo.toml 中代替

[dependencies]
usync = { version = "0.2.1", features = ["nightly"] }

要允许将 MutexGuardRwLock*Guard 发送到其他线程,请启用 send_guard 选项。

许可证

在 MIT 许可证下授权(LICENSE-MIThttp://opensource.org/licenses/MIT)。

依赖项

~160KB