2016-04-21 120 views
4

拿這個例子:爲什麼Arc和Mutex允許我改變一個不可變變量的值?

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;  
}); 

playground

+0

更新:我看了,我認爲它與在互斥體內使用std :: cell - > UnsafeCell https://doc.rust-lang.org/core/cell/struct.UnsafeCell.html但我不知道這是不是真的。 –

回答

7

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

+0

感謝您的時間,我最近閱讀了std :: cell :: *,並在代碼中看到了UnsafeCell,我想我可能是以某種方式相關的,謝謝您的解釋。 –

相關問題