为什么Arc和Mutex允许我更改不可变变量的值?

Ang*_*gel 5 rust

举个例子:

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);
}
Run Code Online (Sandbox Code Playgroud)

不能将不可变的局部变量借用v为可变的

我知道改变mut工作:

std::thread::spawn(move || {
    let mut v = value.lock().unwrap();
    *v += 1;
});
Run Code Online (Sandbox Code Playgroud)

但为什么这样做:

let value = dato.clone();

std::thread::spawn(move || {
    *value.lock().unwrap() += 1;    
});
Run Code Online (Sandbox Code Playgroud)

操场

Vla*_*eev 10

value.lock().unwrap()返回一个type值MutexGuard,它有一个DerefMut实现:

impl<'mutex, T: ?Sized> DerefMut for MutexGuard<'mutex, T> {
    fn deref_mut(&mut self) -> &mut T { ... }
}
Run Code Online (Sandbox Code Playgroud)

DerefMut::deref_mut(x)相当于&mut *x; 当然,DerefMut也可以用于指针下的赋值,就像你的情况一样.

因此,为了*v += 1工作,v应该是一个mut变量 - 否则根本不可能DerefMut::deref_mut被调用.

*value.lock().unwrap() += 1因为now value.lock().unwrap()是一个没有显式绑定的临时变量,所以Rust可以自动分配它的可变性.

Mutex包含UnsafeCell内部的事实与这个特定事物DerefMut直接无关; 然而,它确实意味着Mutex提供了一种称为内部可变性的东西,即它允许通过共享引用来改变其内容.您可以在书中阅读更多内容.