Rust 中是否有一种工具可以锁定多个互斥体同时防止死锁?

问题描述 投票:0回答:3

Rust 中是否有类似 C++

std::lock()
的工具来防止代码中出现死锁:

type Type0 = Arc<Mutex<u8>>;
type Type1 = Arc<Mutex<u16>>;

fn foo(a: Type0, b: Type1) {
    let a_guard = a.lock().unwrap();
    let b_guard = b.lock().unwrap();
}

fn bar(a: Type0, b: Type1) {
    let b_guard = b.lock().unwrap();
    let a_guard = a.lock().unwrap();
}

如果

foo
由线程 0 调用,而
bar
由线程 1 调用,则可能会出现死锁。有什么东西(希望是可变的,因为我可以有两个以上)来帮助我解决这个问题,还是我自己验证锁定顺序的正确性?

来自

std::lock
的文档:

使用死锁避免算法锁定给定的

Lockable
对象
lock1
lock2
...
lockn
以避免死锁。

rust mutex
3个回答
5
投票

,Rust 没有相当于 C++ 的功能

std::lock

基于它似乎不在

std::sync
文档中并且谷歌搜索没有带来任何有用的结果,我对这个断言非常有信心。

为什么不呢?好吧,如果我可以稍微编辑一下,

std::lock
并不像您希望的那样广泛有用。避免死锁并非易事,每种算法都会有可能导致性能不佳甚至活锁的极端情况。不存在万能的死锁避免算法。(参见 std::lock() 是否定义不明确、无法实现或无用?)建议在标准库中放置一个避免死锁的
lock
函数这是一个很好的“默认”选择,并且可能鼓励使用它而不考虑其实现。大多数现实生活中的应用程序可能会使用更简单(且不太通用)的算法。 有些板条箱可以通过其他方式避免死锁。例如,

tracing-mutex

提供了在运行时创建依赖图的锁定类型,如果依赖图包含循环,则会出现恐慌而不是死锁。 parking_lot 有一个实验性的 deadlock_detection 功能(但我不确定它是如何工作的)。奇怪的是,我没有找到任何提供 C++

std::sort
等价的板条箱。

无论如何

,没有什么可以阻止你编写自己的“后退”算法来解决这个问题;它只是不是标准库的一部分。

¹ 公平地说,您可以对 Rust 具有的其他功能进行相同的论证,例如
[T]::sort

。但在许多应用中,排序不是瓶颈,任何相当快的算法就足够了。一般来说,避免死锁不太可能是必要的,而且当它确实出现时,它更有可能对性能敏感。

    


5
投票
Mutex

是一个包含值的元组,那么锁定该元组会同时锁定两个值。


let tuple_mutex = Arc::new(Mutex::new((A, B)));



0
投票
Arc<Mutex<User>>

我编写了一个实用函数来处理它:

async fn ordered_lock<'a, T>(
    m1: &'a Arc<Mutex<T>>,
    m2: &'a Arc<Mutex<T>>,
) -> (MutexGuard<'a, T>, MutexGuard<'a, T>) {
    let l1;
    let l2;
    if Arc::as_ptr(m1) > Arc::as_ptr(m2) {
        l2 = m2.lock().await;
        l1 = m1.lock().await;
    } else {
        l1 = m1.lock().await;
        l2 = m2.lock().await;
    };
    (l1, l2)
}

它与非异步互斥体的工作原理相同,

© www.soinside.com 2019 - 2024. All rights reserved.