#multi-threading #synchronization #bindings #sync

per-thread-mutex

专为封装线程不安全 C 库而设计的同步锁

4 个版本

0.1.3 2024 年 8 月 21 日
0.1.2 2023 年 10 月 17 日
0.1.1 2023 年 9 月 1 日
0.1.0 2023 年 8 月 25 日

并发 中排名 284

Download history 74/week @ 2024-08-15

每月 75 次下载

MPL-2.0 许可证

14KB
156

per-thread-mutex

用于线程不安全 C 库的同步锁。

理由

当与某些 C 库一起工作时,并发访问是不安全的。在 Rust 层面建模此问题可能存在问题,因为语言级别的支持无法在所有情况下强制执行维持安全所需的全部内容。

Send/Sync 可以确保数据结构不会被用于线程之间发送,这提供了部分解决方案。然而,对于某些情况,如果满足两个条件,可以在多线程环境中使用线程不安全的库。

  1. 数据结构是线程本地的,这意味着在线程中创建的任何资源都不会被其他线程发送或使用。这可以通过 Send/Sync 来处理。
  2. 库中不能有并发调用。这不是 Rust 语言级别的特性所解决的问题。

这个 crate 旨在解决第二个要求。

如何使用它?

此互斥锁的预期用途是与 lazy_static 一起作为 Rust 绑定中线程不安全 C 代码的全局变量。在调用库之前应锁定互斥锁。这确保了从不同线程中不会有并发访问,这可能导致不安全的行为。

它是如何工作的?

该锁跟踪两个数据:当前拥有锁获取的线程的线程 ID 以及当前在锁上活动的获取次数。允许从相同的线程 ID 同时进行获取,并且一旦所有锁的获取都被释放,则锁可用。

为什么允许相同的线程多次获取互斥锁?

这主要源于C语言大量使用回调。如果回调被集成到C API中,在Rust绑定中通常的做法是在Rust中编写回调,并编写一个C包装层以将C数据类型转换为Rust数据类型。考虑以下情况:一个API调用在其实现中调用了回调,而这个回调又调用了Rust封装的API调用。这是库的合法使用方式,但会导致对传统的mutex进行两次获取,这将导致在库内部调用时出现死锁。这个锁允许这两次获取都成功执行而不被阻塞,从而防止了传统mutex可能导致的死锁,同时还能防止对库的不安全访问。

依赖项

~130KB