死锁,当通过多个方法访问互斥锁保护结构的不同字段时

deadlock, when different fields of a mutex guarded struct are accessed accross multiple methods

提问人:Harry 提问时间:9/21/2023 最后编辑:cafce25Harry 更新时间:9/21/2023 访问量:41

问:

当互斥锁保护结构的不同字段跨多个函数访问时如何避免死锁,如下所示

use std::sync::Mutex;

#[derive(Default)]
struct InnerData {
    ia: i32,
    ib: i32,
}

#[derive(Default)]
struct OuterData {
    oa: i32,
    ob: Mutex<InnerData>,
}

impl OuterData {
    fn foo(&self) {
        println!("fn foo begin");
        let b_mg = &mut self.ob.lock().unwrap();
        b_mg.ib = 5;
        println!("fn foo end");
    }
}

fn main() {
    let mut outer_data: OuterData = Default::default();
    let b_mg = &mut outer_data.ob.lock().unwrap();
    b_mg.ia = 3;

    if b_mg.ia == 3 {
        outer_data.foo();
    }
}
Rust 互斥锁 死锁

评论

0赞 Jonathon Reinhart 9/21/2023
如果你用谷歌搜索,你会发现很多很好的讨论。rust mutex reentrant
0赞 kmdreko 9/21/2023
@JonathonReinhart很好的讨论,但最终对 OP 没有多大帮助(就其本身而言),因为可重入锁不能授予可变性。

答:

1赞 BallpointBen 9/21/2023 #1

在这种情况下,您可以将其更改为以下内容:

fn main() {
    let mut outer_data: OuterData = Default::default();
    let mut b_mg = outer_data.ob.lock().unwrap(); // own the MutexGuard to be able to drop it
    b_mg.ia = 3;

    if b_mg.ia == 3 {
        drop(b_mg); // unlock the Mutex before calling foo()
        outer_data.foo();
    }
}

评论

0赞 Jonathon Reinhart 9/22/2023
不过,我认为这不一定是正确的解决方案,具体取决于实际用例。这可能会引入检查时间使用时间 (TOCTOU) 错误,因为如果删除互斥锁,则在调用时可能不再是 3。iafoo