1 个不稳定版本

0.1.0 2023年9月28日

#703并发

自定义许可

20KB
365

DFMutex - Rust的无死锁锁

DFMutex是一个为Rust语言提供保证无死锁的Mutex实现的库。其灵感来源于高阶泄漏和无死锁锁以及论文中开发出的微积分。

该库依赖于五个原则来提供一个安全的锁定接口。具体如下

  1. 每个线程只持有任何给定锁的一个引用。
  2. 任何两个线程最多共享一个锁。
  3. 如果我们考虑线程与它们持有的引用的锁之间的连接图,则此图不得有环
  4. 如果我们考虑线程与它们持有的引用的锁之间的连接图,以及锁与它们持有的引用的锁之间的连接图,则此图不得有环。
  5. 如果我们考虑线程与它们持有的引用的锁之间的连接图,以及锁与它们持有的引用的锁之间的连接图,则此图不得有环。此外,每个锁必须恰好有一个拥有引用和一个或多个客户端引用。

这五条规则足以防止在锁定过程中出现任何形式的循环并防止死锁。然而,这些规则也迫使库自带其自己的线程生成方式,并且使用此类锁定接口编写某些程序是不可能的。

用法

在我们来看示例之前,重要的是要注意库提供的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 的轻量级封装,因此它可以与现有的代码库互换使用。需要注意的是,当使用 DFMutexstd::thread::spawn 一起时,没有任何避免死锁的保证。

测试

已经编写了相当数量的测试,但当然可以引入更复杂的示例。

cargo test

致谢

  • Jules Jacobs(荷兰拉德布德大学)
  • Stephanie Balzer(美国卡内基梅隆大学)

依赖关系

~310KB