5 个不稳定版本
0.3.0 | 2023年9月13日 |
---|---|
0.2.1 | 2022年5月23日 |
0.1.2 | 2021年5月27日 |
#264 在 并发
每月 93 次下载
在 bevy_schedule_dispatch 中使用
73KB
1K SLoC
追踪互斥锁
通过以一致顺序获取它们,或否则,避免互斥锁中的死锁。
背景
在任何使用互斥锁或锁的代码中,你很快就会遇到死锁的可能性。假设有两个互斥锁 Foo
和 Bar
,你就可以已经死锁,前提是一个线程首先锁定 Foo
然后尝试获取 Bar
,另一个首先获取 Bar
然后尝试获取 Foo
。现在两个线程都在等待对方释放它们已经拥有的锁。
绕过这个问题的简单方法之一是确保当你需要同时获取 Foo
和 Bar
时,你应该首先获取 Foo
,然后你永远不会死锁。当然,对于只有两个互斥锁的情况,这很容易跟踪,但是一旦你的代码开始增长,你可能就会失去对这些依赖的跟踪。这正是这个 crate 的用武之地。
这个 crate 跟踪你在代码中获取锁的顺序,试图根据它构建一个依赖树,如果依赖关系会创建循环,则会引发 panic。它提供了具有相同 API 的现有同步原语的替换方案,应该是一个直接替换。
本 crate 受到 这篇博客文章 的启发,该文章引用了 Abseil 为其互斥锁实现的一种类似行为。这篇文章深入探讨了具体的实现方法。
用法
将此依赖项添加到你的 Cargo.lock
文件中,就像其他任何依赖项一样
[dependencies]
tracing-mutex = "0.2"
然后使用此库提供的锁而不是你通常使用的锁。在 stdsync
模块中可以找到 std::sync
中的同步原语的替换方案。计划支持其他同步原语。
use tracing_mutex::stdsync::Mutex;
let some_mutex = Mutex::new(42);
*some_mutex.lock().unwrap() += 1;
println!("{:?}", some_mutex);
锁之间的相互依赖关系会自动跟踪。如果任何锁定操作会在您的锁之间引入循环依赖,则操作会引发恐慌。这允许您立即发现循环依赖,而不是在生产环境中最终感到惊讶。
互斥锁跟踪是高效的,但它并不是完全没有开销。如果您在生产环境中无法承受性能损失,此库还提供了仅调试跟踪。在 stdsync
模块中也可以找到的 DebugMutex
,当启用调试断言时,它评估为 TracingMutex
,当未启用时,它评估为 Mutex
。还有其他类似的辅助类型可用于其他同步原语。
最低支持的 Rust 版本是 1.70。提高这个版本不被视为破坏性更改,但如果可能,将在与 semver 兼容的版本中避免它。
特性
- 所有锁定原语的依赖关系跟踪包装器
- 可选的发布模式代码退出的选项
- 支持以下原语
std::sync
parking_lot
- 任何实现了
lock_api
特性的库
未来改进
- 改进锁定跟踪的性能
- 可选的日志记录,以便更容易进行调试
- 在检测到循环依赖时提供更好的和可配置的错误处理
- 支持其他锁定库
- 支持异步锁定库
- 支持
Send
互斥锁守护者
注意: parking_lot
已经开始开发自己的死锁检测机制,它的工作方式不同。两者可以互补。
许可证
根据您的选择,许可为以下之一
- Apache 许可证第 2 版,(LICENSE-APACHE 或 https://apache.ac.cn/licenses/LICENSE-2.0)
- MIT 许可证 (LICENSE-MIT 或 http://opensource.org/licenses/MIT)
。
贡献
除非您明确表示否则,您提交的任何贡献,根据 Apache-2.0 许可证定义,均应按上述方式双许可,而无需任何附加条款或条件。
依赖关系
~0–5MB