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

时间:2014-09-10 21:56:09

标签: mutex rust

获取结构的字段以供阅读 rust playpen

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不会改变任何内容并且不会声明变异,尤其是{ {1}}。

要使此代码正常工作,我可以使用&self声明m2并且一切正常,但为什么我需要这里的mut并且有更好的方法来调用let mut m2 = m.lock();声明m2.get()变量的方式与它适用于m2的方式类似,我声明它是不可变的,并且仍允许我调用t

2 个答案:

答案 0 :(得分:4)

是的,如果两者都可用,编译器倾向于优先于deref_mut调用deref。在您的情况下,deref就足够了,但隐式解引用机制会选择deref_mut,然后抱怨m2不可变。

要添加到reem所说的内容,锁定对象 同时实现DerefDerefMut,如果您不需要可变借用,则可以获取不可改变的,通过明确地重新借贷它是不可改变的:

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

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

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

然后允许

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

答案 1 :(得分:3)

这是由于目前Deref一系列特征略有限制 - 即现在为同一类型同时实施DerefDerefMut因行为而略有不同方法的autoderef,即deref_mut始终被调用,甚至可以获得&个引用。

因此,MutexGuard需要是可变的,以便您调用需要&self的方法。通常,Mutex的不可变用法很少见,并且RWLock分别支持读锁和写锁,因此它更适合这种用例,因为它允许并发读锁。