gpt4 book ai didi

Is there a facility to lock multiple mutexes in Rust while preventing deadlocking?(有没有一种工具可以锁定Rust中的多个互斥锁,同时防止死锁?)

转载 作者:bug小助手 更新时间:2023-10-26 20:33:15 27 4
gpt4 key购买 nike



Is there a C++ std::lock() like facility in Rust to prevent deadlocking in code like this:

在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();
}


If foo is called by thread-0 and bar by thread-1 there is a chance of deadlock. Is there something, hopefully variadic because I can have more than 2, to help me with this or am I all on my own verifying the correctness of order of locking?

如果线程0调用foo,而线程1调用bar,则存在死锁的可能性。有什么可以帮助我的吗,希望是可变的,因为我可以有超过2个,还是我自己验证锁定顺序的正确性?



From the documentation for std::lock:

来自std::lock的文档:




Locks the given Lockable objects lock1, lock2, ..., lockn using a deadlock avoidance algorithm to avoid deadlock.



更多回答

Admittedly I don't know how std::lock works, but (unless you follow mmstick's answer in lumping the data together and locking/unlocking it at once) I don't see how you could ever guarantee no deadlocks. Sure, you could write a macro to do them in the right order -- but then you've just mutated the problem of checking that you always lock them in the right order into the barely-easier problem of checking that you always use the macro and never call .lock() directly. Right?

诚然,我不知道std::lock是如何工作的,但(除非您遵循MmStick的答案,将数据集中在一起并立即锁定/解锁),否则我看不出您如何保证不会出现死锁。当然,您可以编写一个宏来按正确的顺序执行它们--但这样做只是将检查是否始终以正确的顺序锁定它们的问题变成了检查您始终使用宏并且从不直接调用.lock()的问题。对吗?

优秀答案推荐

No, Rust does not have a function equivalent to C++'s std::lock.

不,Rust没有与C++的S Std::Lock等价的函数。


Based on the fact that it doesn't seem to be in the std::sync documentation and Googling brings up nothing useful, I'm pretty confident in this assertion.

基于这样一个事实,它似乎不在std::sync文档中,而且Google没有带来任何有用的东西,我对这个断言相当有信心。


Why not? Well, if I may editorialize a bit, std::lock isn't as broadly useful as you might hope. Deadlock avoidance is nontrivial and every algorithm will have plausible corner cases that result in poor performance or even livelock. There is no one-size-fits-all deadlock avoidance algorithm.¹ (See Is std::lock() ill-defined, unimplementable, or useless?) Putting a deadlock-avoiding lock function in the standard library suggests that it's a good default choice, and perhaps encourages its use without regard for its implementation. Most real-life applications probably would do as well with a simpler (and less general-purpose) algorithm.

为什么不行?好吧,如果我可以发表一点社论的话,std::lock并不像您希望的那样广泛有用。避免死锁并不是一件容易的事,而且每个算法都会出现可能导致性能低下甚至活锁的死角情况。没有一刀切的死锁避免算法(参见std::lock()定义错误、无法实现还是毫无用处?)将避免死锁的锁函数放在标准库中表明它是一个很好的默认选择,并且可能鼓励使用它,而不考虑它的实现。大多数现实生活中的应用程序可能会使用更简单(且不太通用)的算法。


There are crates that provide deadlock avoidance by other means. For instance, tracing-mutex provides locking types that create a dependency graph at runtime and will panic instead of deadlocking if the dependency graph contains a cycle. parking_lot has an experimental deadlock_detection feature (but I'm not sure how it works). Curiously, I didn't find any crates that provide a C++ std::sort equivalent with backing off.

有一些板条箱可以通过其他方式避免僵局。例如,跟踪互斥锁提供了在运行时创建依赖图的锁定类型,如果依赖图包含循环,则会死机而不是死锁。Parking_lot有一个实验性的死锁检测功能(但我不确定它是如何工作的)。奇怪的是,我没有找到任何提供等同于后退的C++std::Sort的板条箱。


Anyway, nothing stops you writing your own "backing off" algorithm to solve this problem; it's just not part of the standard library.

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




¹ In fairness, you could make the same argument for other functions Rust does have, like [T]::sort. But there are many applications where sorting is not a bottleneck and any reasonably fast algorithm is good enough. Deadlock avoidance is both less likely to be necessary in general, and more likely to be performance-sensitive when it does appear.

?公平地说,您可以对Rust拥有的其他函数进行相同的论证,如[T]::Sort。但在许多应用程序中,排序不是瓶颈,任何相当快的算法都足够好。通常情况下,避免死锁的可能性较小,但当死锁确实出现时,更有可能对性能敏感。



This is easily solved if the Mutex is a tuple with the contained values, so that locking the tuple locks both values simultaneously.

如果Mutex是一个包含值的元组,那么这个问题很容易解决,因此锁定该元组可以同时锁定这两个值。



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


I ran into this issue where I have a mutex for every logged in user. When two users interact, I need to lock both users. To solve this I needed some sorting mechanism to order the locks. Since I'm using Arc<Mutex<User>> I wrote a utility function to handle it:

我遇到了这个问题,每个登录的用户都有一个互斥体。当两个用户交互时,我需要锁定两个用户。为了解决这个问题,我需要一些排序机制来对锁进行排序。由于我使用的是Arc ,所以我编写了一个实用函数来处理它:


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)
}

It'd work the same with non-async mutex,

它对非异步互斥锁的作用是一样的,


更多回答

Excellent point, but might want to retain the flexibility of independent values.

很好的观点,但可能想要保留独立价值观的灵活性。

We can view tuple is just a single type - so that is basically Mutexing a single type. What i am looking for though is a solution to different Mutexs. For granularity you might not want to always lump them into a single tuple/type - then you are sacrificing cases where they could function independent of each other which abound in my code. It's really a difference betwen Arc<Mutexing the whole struct vs Arc<Mutexing individual fields. The latter gives much finer control and my question was about that - is there a facility similar to std::lock of c++.

我们可以看到元组只是一个单一的类型-所以这基本上是互斥一个单一的类型。我正在寻找的是一个解决方案,但不同的互斥。对于粒度,你可能不想总是把它们集中到一个元组/类型中--那么你就牺牲了它们可以相互独立运行的情况,而这些情况在我的代码中比比皆是。Arc

Does this really allow us to lock the mutextes simultaneously, or are they in reality locked one after the other? If so, what order are the mutextes unlocked in?

这是否真的允许我们同时锁定互斥锁,或者它们实际上是一个接一个地锁定的?如果是,互斥锁的解锁顺序是什么?

@SimonElliott There is only one Mutex in this solution; it is used to lock a compound value. The values are locked simultaneously because they are controlled by the same mutex.

@SimonElliott此解决方案中只有一个Mutex;它用于锁定复合值。这些值被同时锁定,因为它们由相同的互斥体控制。

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com