Why do Arc and Mutex allow me to change the value of an immutable variable?

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 take an immutable local variable vas mutable

I know that switching to mutworks:

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

but why does it work:

let value = dato.clone();

std::thread::spawn(move || {
    *value.lock().unwrap() += 1;    
});

playground

+4
source share
1 answer

value.lock().unwrap()returns a value of the type MutexGuardthat the implementation has DerefMut:

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

DerefMut::deref_mut(x)equivalently &mut *x; Naturally, it is DerefMutalso used for appointments under the pointer, as in your case.

Therefore, for the *v += 1operation vto be a variable mut- otherwise it would be impossible to call DerefMut::deref_mutat all.

*value.lock().unwrap() += 1 , value.lock().unwrap() , Rust .

, Mutex UnsafeCell, DerefMut; , Mutex -, , .. . .

+8

All Articles