获取结构的字段以供阅读 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
。
答案 0 :(得分:4)
是的,如果两者都可用,编译器倾向于优先于deref_mut
调用deref
。在您的情况下,deref
就足够了,但隐式解引用机制会选择deref_mut
,然后抱怨m2
不可变。
要添加到reem所说的内容,锁定对象 同时实现Deref
和DerefMut
,如果您不需要可变借用,则可以获取不可改变的,通过明确地重新借贷它是不可改变的:
println!("m2.get() = {}", (&*m2).get());
如果你需要这种访问,你也可以写
let m2 = m.lock();
let m2 = &*m2;
然后允许
println!("m2.get() = {}", m2.get());
答案 1 :(得分:3)
这是由于目前Deref
一系列特征略有限制 - 即现在为同一类型同时实施Deref
和DerefMut
因行为而略有不同方法的autoderef,即deref_mut
始终被调用,甚至可以获得&
个引用。
因此,MutexGuard
需要是可变的,以便您调用需要&self
的方法。通常,Mutex
的不可变用法很少见,并且RWLock
分别支持读锁和写锁,因此它更适合这种用例,因为它允许并发读锁。