如何使方法不需要锁定互斥的可变自我



>访问结构体的字段以进行读取生锈游戏围栏:

use std::sync::Mutex;
#[deriving(Show)]
struct Test{
    a: uint,
}
impl Test{
    fn new() -> Test{
        Test { a: 0}
    }
    fn get(&self) -> uint {
        self.a
    }
}
fn main() {
    let t = Test{a: 42};
    let m = Mutex::new(Test::new());
    println!("Getting t: {} where t.a = {}", t.get(), t.a);
    {
        let m2 = m.lock();
        println!("m2.a = {}", m2.a); // works
        //println!("m2.get() = {}", m2.get()); // error: cannot borrow immutable local variable `m2` as mutable
    }
}

因此,在这种情况下,访问字段m2.a有效,但调用m2.get()需要m2可变,尽管get不会改变任何东西,也不会声明为正在改变任何东西,尤其是不&self

为了使这段代码正常工作,我可以用 let mut m2 = m.lock(); 声明 m2 并且一切正常,但是为什么我在这里需要那个 mut,有没有更好的方法来调用m2.get()而不声明m2可变的,因为它适用于我声明为不可变并且仍然允许我调用t.get() t

是的,编译器倾向于调用deref_mut而不是deref,以防两者都可用。在您的情况下,deref就足够了并且有效,但隐式取消引用机制会选择deref_mut,然后抱怨m2不可变。

为了补充 reem 所说的,lock 对象确实实现了 DerefDerefMut 这两个对象,如果你不需要可变借用,你可以通过显式地不可变地重新借用它来获取不可变的借用:

println!("m2.get() = {}", (&*m2).get());

如果这种访问是你所需要的,你也可以写

let m2 = m.lock();
let m2 = &*m2;

然后允许

println!("m2.get() = {}", m2.get());
这是

由于现在Deref系列的特征略有限制 - 即现在为同一类型实现DerefDerefMut由于方法的 autoderef 行为而略有中断,即总是调用deref_mut,甚至为了获取&引用。

因此,MutexGuard需要可变才能调用需要&self的方法。通常,Mutex的不可变用途很少见,而分别支持读写锁定的 RWLock 更适合此用例,因为它允许并发读锁定。

最新更新