【问题标题】:Is there a facility to lock multiple mutexes in Rust while preventing deadlocking?是否有在 Rust 中锁定多个互斥锁同时防止死锁的工具?
【发布时间】:2021-10-02 00:02:10
【问题描述】:

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 被thread-0 调用,bar 被thread-1 调用,则有可能出现死锁。有什么东西可以帮助我解决这个问题,希望是可变的,因为我可以有超过 2 个,还是我自己验证锁定顺序的正确性?

来自the documentation for std::lock:

使用死锁避免算法锁定给定的Lockable 对象lock1、lock2、...、lockn 以避免死锁。

【问题讨论】:

  • 诚然,我不知道std::lock 是如何工作的,但是(除非你按照 mmstick 的回答将数据集中在一起并立即锁定/解锁它)我不知道你怎么能保证没有死锁。当然,您可以编写一个宏来以正确的顺序执行它们 - 但是您只是将检查您是否始终以正确的顺序锁定它们的问题变成了几乎不简单的问题检查您是否始终使用宏并且从不直接调用 .lock()。对吗?

标签: rust mutex


【解决方案1】:

否,Rust 没有与 C++ 的 std::lock 等效的函数。

基于它似乎不在std::sync documentation 中并且谷歌搜索没有任何有用的事实,我对这个断言非常有信心。

为什么不呢?好吧,如果我可以编辑一下,std::lock 并没有你希望的那么广泛有用。避免死锁是非常重要的,每个算法都会有可能导致性能不佳甚至活锁的极端情况。没有万能的死锁避免算法。¹(参见Is std::lock() ill-defined, unimplementable, or useless?)在标准库中放置一个避免死锁的lock 函数表明这是一个很好的默认选择,并且也许鼓励使用它而不考虑其实施。大多数现实生活中的应用程序可能会使用更简单(且通用性较低)的算法。

有些板条箱可以通过其他方式避免死锁。例如,tracing-mutex 提供了在运行时创建依赖图的锁定类型,如果依赖图包含循环,则会出现恐慌而不是死锁。 parking_lot 有一个实验性的 deadlock_detection 功能(但我不确定它是如何工作的)。奇怪的是,我没有找到任何提供 C++ std::sort 等价物的 crate。

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


¹ 公平地说,你可以为 Rust 拥有的其他功能提出相同的论点,例如 [T]::sort。但是有许多应用程序排序不是瓶颈,任何合理快速的算法都足够好。避免死锁通常不太可能是必要的,而且当它出现时更有可能对性能敏感。

【讨论】:

    【解决方案2】:

    如果Mutex 是一个包含值的元组,这很容易解决,因此锁定元组会同时锁定两个值。

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

    【讨论】:

    • 好点,但可能希望保留独立值的灵活性。
    • 我们可以看到 tuple 只是一个单一的类型 - 所以这基本上是 Mutexing 一个单一的类型。我正在寻找的是不同互斥体的解决方案。对于粒度,您可能不想总是将它们集中到单个元组/类型中 - 然后您会牺牲它们可以相互独立运行的情况,这在我的代码中比比皆是。 Arc&lt;Mutexing 整个 struct 与 Arc&lt;Mutexing 各个字段之间确实存在差异。后者提供了更好的控制,我的问题是关于这个 - 是否有类似于 c++ 的std::lock 的设施。
    • 这真的允许我们同时锁定互斥锁,还是它们实际上是一个接一个地锁定?如果是这样,互斥锁的解锁顺序是什么?
    • @SimonElliott 此解决方案中只有一个Mutex;它用于锁定复合值。这些值被同时锁定,因为它们由同一个互斥锁控制。
    猜你喜欢
    • 1970-01-01
    • 2011-02-14
    • 2018-06-10
    • 1970-01-01
    • 2023-03-09
    • 1970-01-01
    • 1970-01-01
    • 2015-10-26
    • 1970-01-01
    相关资源
    最近更新 更多