举个例子:
fn main() {
let dato = std::sync::Arc::new(std::sync::Mutex::new(1u8));
for _ in 0..3 {
let value = dato.clone();
std::thread::spawn(move || {
let v = value.lock().unwrap();
*v += 1; // <- Error
});
}
std::thread::sleep(std::time::Duration::from_secs(1u64));
println!("{:?}", dato);
}
不能将不可变局部变量
借用v
作为可变
我知道更改为mut
有效:
std::thread::spawn(move || {
let mut v = value.lock().unwrap();
*v += 1;
});
但为什么这样做:
let value = dato.clone();
std::thread::spawn(move || {
*value.lock().unwrap() += 1;
});
答案 0 :(得分:9)
value.lock().unwrap()
返回类型为MutexGuard
的值,其值为DerefMut
:
impl<'mutex, T: ?Sized> DerefMut for MutexGuard<'mutex, T> {
fn deref_mut(&mut self) -> &mut T { ... }
}
DerefMut::deref_mut(x)
相当于&mut *x
;当然,DerefMut
也用于指针下的赋值,就像你的情况一样。
因此,要使*v += 1
生效,v
应该是mut
变量 - 否则根本不可能调用DerefMut::deref_mut
。
*value.lock().unwrap() += 1
有效,因为现在value.lock().unwrap()
是一个没有显式绑定的临时变量,因此Rust可以自动分配其可变性。
Mutex
内部包含UnsafeCell
的事实与DerefMut
直接相关的这一事实无关;但是,它确实意味着Mutex
提供了一种称为内部可变性的东西,即它允许通过共享引用来改变其内容。您可以在其上阅读更多内容in the book。