1 个不稳定版本
0.1.0 | 2023年9月28日 |
---|
#703 在 并发
20KB
365 行
DFMutex - Rust的无死锁锁
DFMutex是一个为Rust语言提供保证无死锁的Mutex实现的库。其灵感来源于高阶泄漏和无死锁锁以及论文中开发出的微积分。
该库依赖于五个原则来提供一个安全的锁定接口。具体如下
- 每个线程只持有任何给定锁的一个引用。
- 任何两个线程最多共享一个锁。
- 如果我们考虑线程与它们持有的引用的锁之间的连接图,则此图不得有环
- 如果我们考虑线程与它们持有的引用的锁之间的连接图,以及锁与它们持有的引用的锁之间的连接图,则此图不得有环。
- 如果我们考虑线程与它们持有的引用的锁之间的连接图,以及锁与它们持有的引用的锁之间的连接图,则此图不得有环。此外,每个锁必须恰好有一个拥有引用和一个或多个客户端引用。
这五条规则足以防止在锁定过程中出现任何形式的循环并防止死锁。然而,这些规则也迫使库自带其自己的线程生成方式,并且使用此类锁定接口编写某些程序是不可能的。
用法
在我们来看示例之前,重要的是要注意库提供的API的变化。该库在dfmutex::DFMutex
下提供核心锁,并使用自己的dfmutex::spawn
方法来生成线程。重要的是要注意spawn
方法的函数签名
fn spawn<D, T, F>(dfm: &DFMutex<D>, f: F) -> JoinHandle<T>
where
F: FnOnce(DFMutex<D>) -> T + Send + 'static,
D: Send + 'static,
T: Send + 'static,
{
// ...
}
该函数接受一个DFMutex
的共享引用和一个接受DFMutex
的所有权值的闭包。当生成线程时,具有共享引用的Mutex被克隆并作为闭包的参数传递给线程以执行。此操作的结果是返回新创建线程的JoinHandle
。
现在来看它的用法
use dfmutex::{DFMutex, spawn};
fn main() {
// Create a Mutex with any owned value
let m = DFMutex::new(String::from("Lorem Ipsum"));
// Create a closure to pass in the thread.
// The type of the created Mutex above should be same as the
// argument to the closure.
let closure = |mut dfm: DFMutex<String>| {
let data = dfm.lock().unwrap();
// Use the data
println!("{}", data);
};
// Spawn 8 threads and store their handles
let mut handles = Vec::new();
for _ in 0..8 {
handles.push(spawn(&m, closure));
}
// Join all the threads
for handle in handles.into_iter() {
handle.join().unwrap();
}
}
DFMutex
只是对 std::sync::Mutex
的轻量级封装,因此它可以与现有的代码库互换使用。需要注意的是,当使用 DFMutex
与 std::thread::spawn
一起时,没有任何避免死锁的保证。
测试
已经编写了相当数量的测试,但当然可以引入更复杂的示例。
cargo test
致谢
- Jules Jacobs(荷兰拉德布德大学)
- Stephanie Balzer(美国卡内基梅隆大学)
依赖关系
~310KB