在防止死锁的同时,是否有一种工具可以在 Rust 中锁定多个互斥量?
Is there a facility to lock multiple mutexes in Rust while preventing deadlocking?
在 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 调用,则有可能发生死锁。有什么东西,希望可变参数,因为我可以有超过 2 个,来帮助我解决这个问题,还是我自己验证锁定顺序的正确性?
来自 the documentation for std::lock
:
Locks the given Lockable
objects lock1
, lock2
, ...
, lockn
using a deadlock avoidance algorithm to avoid deadlock.
如果 Mutex
是一个包含值的元组,这很容易解决,因此锁定元组会同时锁定两个值。
let tuple_mutex = Arc::new(Mutex::new((A, B)));
No, Rust 没有等同于 C++ 的函数 std::lock
.
基于它似乎不在 std::sync
documentation 中并且谷歌搜索没有提供任何有用信息的事实,我对这个断言非常有信心。
为什么不呢?好吧,如果我可以编辑一下,std::lock
并不像您希望的那样广泛有用。死锁避免是非常重要的,每个算法都会有可能导致性能不佳甚至活锁的极端情况。没有万能的死锁避免算法。¹(参见 Is std::lock() ill-defined, unimplementable, or useless?)在标准库中放置一个避免死锁的 lock
函数表明它是一个很好的 default 选择,并且可能鼓励使用它而不考虑其实现。大多数现实生活中的应用程序可能会使用更简单(且不太通用)的算法。
有些 crate 可以通过其他方式避免死锁。例如,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 有一个实验性的 deadlock_detection
功能(但我不确定它是如何工作的)。奇怪的是,我没有找到任何提供 C++ std::sort
等效于后退的板条箱。
无论如何,没有什么能阻止您编写自己的“后退”算法来解决这个问题;它只是不是标准库的一部分。
¹ 公平地说,您可以对 Rust 确实具有的其他函数进行相同的论证,例如 [T]::sort
。但有许多应用程序排序不是瓶颈,任何相当快的算法都足够好。死锁避免通常不太可能是必需的,而且当它出现时更有可能对性能敏感。
在 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 调用,则有可能发生死锁。有什么东西,希望可变参数,因为我可以有超过 2 个,来帮助我解决这个问题,还是我自己验证锁定顺序的正确性?
来自 the documentation for std::lock
:
Locks the given
Lockable
objectslock1
,lock2
,...
,lockn
using a deadlock avoidance algorithm to avoid deadlock.
如果 Mutex
是一个包含值的元组,这很容易解决,因此锁定元组会同时锁定两个值。
let tuple_mutex = Arc::new(Mutex::new((A, B)));
No, Rust 没有等同于 C++ 的函数 std::lock
.
基于它似乎不在 std::sync
documentation 中并且谷歌搜索没有提供任何有用信息的事实,我对这个断言非常有信心。
为什么不呢?好吧,如果我可以编辑一下,std::lock
并不像您希望的那样广泛有用。死锁避免是非常重要的,每个算法都会有可能导致性能不佳甚至活锁的极端情况。没有万能的死锁避免算法。¹(参见 Is std::lock() ill-defined, unimplementable, or useless?)在标准库中放置一个避免死锁的 lock
函数表明它是一个很好的 default 选择,并且可能鼓励使用它而不考虑其实现。大多数现实生活中的应用程序可能会使用更简单(且不太通用)的算法。
有些 crate 可以通过其他方式避免死锁。例如,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 有一个实验性的 deadlock_detection
功能(但我不确定它是如何工作的)。奇怪的是,我没有找到任何提供 C++ std::sort
等效于后退的板条箱。
无论如何,没有什么能阻止您编写自己的“后退”算法来解决这个问题;它只是不是标准库的一部分。
¹ 公平地说,您可以对 Rust 确实具有的其他函数进行相同的论证,例如 [T]::sort
。但有许多应用程序排序不是瓶颈,任何相当快的算法都足够好。死锁避免通常不太可能是必需的,而且当它出现时更有可能对性能敏感。