有人可以解释一下为什么当
borrow_mut()
在 ReentrantMutexGuard
上执行时我的代码会出现恐慌。这是我的代码
use std::sync::Mutex;
use std::cell::RefCell;
use parking_lot::ReentrantMutex;
#[derive(Default)]
struct InnerData {
ia: i32,
ib: i32,
}
#[derive(Default)]
struct OuterData {
oa: i32,
ob: ReentrantMutex<RefCell<InnerData>>,
}
impl OuterData {
fn foo(&self) {
println!("fn foo begin");
let mut b_mg = self.ob.lock();
let mut b_data = b_mg.borrow_mut();
println!("after acquiring lock");
if b_data.ia == 3 {
b_data.ib = 5;
}
println!("fn foo end");
}
}
fn main() {
let mut outer_data: OuterData = Default::default();
let mut b_mg = outer_data.ob.lock();
let mut b_data = b_mg.borrow_mut();
b_data.ia = 3;
if b_data.ia == 3 {
outer_data.foo();
}
}
总结一下评论:可重入互斥体将授予您在子作用域中保持锁定时不可变的访问子作用域中的内部值,但是
RefCell
将 not 允许在父作用域的 RefMut
时对其值进行可变访问
仍然存在,以遵守 Rust 的引用保证。
幸运的是,您不需要删除锁保护,但您需要删除
RefMut
,以便在调用可能想要访问数据的嵌套函数之前释放其对数据的独占保留。在你的代码中:
fn main() {
let mut outer_data: OuterData = Default::default();
let mut b_mg = outer_data.ob.lock();
let mut b_data = b_mg.borrow_mut();
b_data.ia = 3;
drop(b_data); // <----------------
outer_data.foo();
}
或者一些变化。您可能希望更好地封装内部可变性(以限制
RefMut
的活动时间),以更好地避免此问题。