为什么采用不可变 `&self` 的方法可以使用互斥量修改字段中的数据?
Why can method taking immutable `&self` modify data in field with mutex?
考虑以下代码(也在playground上):
use std::{collections::HashMap, sync::Mutex};
struct MyStruct {
dummy_map: Mutex<HashMap<i64, i64>>,
}
impl MyStruct {
pub fn new() -> Self {
MyStruct {
dummy_map: Mutex::new(Default::default()),
}
}
pub fn insert(&self, key: i64, val: i64) { // <-- immutable &self
self.dummy_map.lock().unwrap().insert(key, val); // <-- insert in dummy_map
}
}
fn main() {
let s = MyStruct::new();
let key = 1;
s.insert(key, 1);
assert!(s.dummy_map.lock().unwrap().get(&key).is_some());
}
代码运行时没有恐慌,这意味着 insert
采用不可变的 &self
,但它仍然可以插入到地图(包裹在 Mutex
中)。
这怎么可能?
insert
服用 &mut self
会更好吗?表示一个字段被修改...
如果 dummy_map
未包含在 Mutex
中,则代码无法编译(如我所料)。参见 this playground。
mut
在 Rust 中有点用词不当,它实际上意味着“独占访问”(你需要能够改变一个值,但稍微更通用)。在这种情况下,您显然无法获得对 Mutex
本身的独占访问权(因为重点是在线程之间共享它),因此您也无法获得对 self
的独占访问权。但是,您可以获得对 Mutex
内数据的临时独占访问权,此时可以对其进行变异。有点像 Cell
和 RefCell
的情况。
A Mutex
是实现“内部可变性”的 Rust 类型之一(参见 the docs for Cell
讨论)。
简而言之,实现“内部可变性”的类型绕过了编译时所有权检查,支持运行时检查。在这种情况下,Mutex
通过确保只有一个线程可以使用其 lock()
and try_lock()
方法访问数据来在运行时强制执行可变性规则。
两种锁定方法 return 一个拥有的 MutexGuard
可以分别通过 Deref
和 DerefMut
特征提供对数据的只读和可变访问。
最后,这意味着需要mut
的变量是return编辑的MutexGuard
,而不是Mutex
本身。
考虑以下代码(也在playground上):
use std::{collections::HashMap, sync::Mutex};
struct MyStruct {
dummy_map: Mutex<HashMap<i64, i64>>,
}
impl MyStruct {
pub fn new() -> Self {
MyStruct {
dummy_map: Mutex::new(Default::default()),
}
}
pub fn insert(&self, key: i64, val: i64) { // <-- immutable &self
self.dummy_map.lock().unwrap().insert(key, val); // <-- insert in dummy_map
}
}
fn main() {
let s = MyStruct::new();
let key = 1;
s.insert(key, 1);
assert!(s.dummy_map.lock().unwrap().get(&key).is_some());
}
代码运行时没有恐慌,这意味着 insert
采用不可变的 &self
,但它仍然可以插入到地图(包裹在 Mutex
中)。
这怎么可能?
insert
服用 &mut self
会更好吗?表示一个字段被修改...
如果 dummy_map
未包含在 Mutex
中,则代码无法编译(如我所料)。参见 this playground。
mut
在 Rust 中有点用词不当,它实际上意味着“独占访问”(你需要能够改变一个值,但稍微更通用)。在这种情况下,您显然无法获得对 Mutex
本身的独占访问权(因为重点是在线程之间共享它),因此您也无法获得对 self
的独占访问权。但是,您可以获得对 Mutex
内数据的临时独占访问权,此时可以对其进行变异。有点像 Cell
和 RefCell
的情况。
A Mutex
是实现“内部可变性”的 Rust 类型之一(参见 the docs for Cell
讨论)。
简而言之,实现“内部可变性”的类型绕过了编译时所有权检查,支持运行时检查。在这种情况下,Mutex
通过确保只有一个线程可以使用其 lock()
and try_lock()
方法访问数据来在运行时强制执行可变性规则。
两种锁定方法 return 一个拥有的 MutexGuard
可以分别通过 Deref
和 DerefMut
特征提供对数据的只读和可变访问。
最后,这意味着需要mut
的变量是return编辑的MutexGuard
,而不是Mutex
本身。