为什么 Arc 和 Mutex 允许我更改不可变变量的值? [英] Why do Arc and Mutex allow me to change the value of an immutable variable?
问题描述
举个例子:
fn main() {让 dato = std::sync::Arc::new(std::sync::Mutex::new(1u8));对于 _ 在 0..3 {让值 = dato.clone();std::thread::spawn(移动||{让 v = value.lock().unwrap();*v += 1;//<- 错误});}std::thread::sleep(std::time::Duration::from_secs(1u64));println!("{:?}", 数据);}
<块引用>
不能借用不可变的局部变量 v
作为可变的
我知道更改为 mut
是有效的:
std::thread::spawn(move || {让 mut v = value.lock().unwrap();*v += 1;});
但是为什么这样做:
let value = dato.clone();std::thread::spawn(移动||{*value.lock().unwrap() += 1;});
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
提供了一种称为内部可变性的东西,即它允许人们通过共享引用来改变其内容.您可以在书中阅读更多相关内容.
Take this example:
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);
}
cannot borrow immutable local variable
v
as mutable
I know that changing to mut
works:
std::thread::spawn(move || {
let mut v = value.lock().unwrap();
*v += 1;
});
but why does this work:
let value = dato.clone();
std::thread::spawn(move || {
*value.lock().unwrap() += 1;
});
value.lock().unwrap()
returns a value of type MutexGuard
, which has a DerefMut
implementation:
impl<'mutex, T: ?Sized> DerefMut for MutexGuard<'mutex, T> {
fn deref_mut(&mut self) -> &mut T { ... }
}
DerefMut::deref_mut(x)
is equivalent to &mut *x
; naturally, DerefMut
is also used for assignments under the pointer, like in your case.
Therefore, for *v += 1
to work, v
should be a mut
variable - otherwise it would be impossible for DerefMut::deref_mut
to be invoked at all.
*value.lock().unwrap() += 1
works because now value.lock().unwrap()
is a temporary variable without an explicit binding, so Rust is free to assign its mutability automatically.
The fact that Mutex
contains an UnsafeCell
inside is not related to this particular thing about DerefMut
directly; however, it does mean that Mutex
provides something called internal mutability, i.e. it allows one to mutate its contents through a shared reference. You can read more on it in the book.
这篇关于为什么 Arc 和 Mutex 允许我更改不可变变量的值?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!