这是取自Mutex
documentation:
use std::sync::{Arc, Mutex};
use std::sync::mpsc::channel;
use std::thread;
const N: usize = 10;
fn main() {
let data = Arc::new(Mutex::new(0));
let (tx,rx) = channel();
for _ in 0..N{
let (data, tx) = (data.clone(), tx.clone());
thread::spawn(move || {
// snippet
});
}
rx.recv().unwrap();
}
我的问题是snippet
评论的位置。它以
let mut data = data.lock().unwrap();
*data += 1;
if *data == N {
tx.send(()).unwrap();
}
数据类型为Arc<Mutex<usize>>
,因此在调用data.lock()
时,我认为Arc
被自动解除引用,而usize
被分配给data
}。为什么我们需要再次在*
前面data
取消引用它?
以下代码首先取消引用Arc
,然后仅使用usize
,也可以代替代码段。
let mut data = *data.lock().unwrap();
data += 1;
if data == N {
tx.send(()).unwrap();
}
答案 0 :(得分:10)
关注文档。从Arc<T>
开始:
Arc::lock
是否存在?不。检查Deref
。Deref::Target
是T
。检查Mutex<T>
。Mutex::lock
是否存在? Yes。它返回LockResult<MutexGuard<T>>
。unwrap
来自哪里? LockResult<T>
是Result<T, PoisonError<T>>
的同义词。所以它是Result::unwrap
,结果是MutexGuard<T>
。data
的类型为MutexGuard<usize>
。所以这是错误的:
因此,在致电
data.lock()
时,我认为Arc
被自动解除引用,而usize
被分配给data
。
因此,问题不在于您无法直接分配,而是如何在所有分配usize
值。再次,按照文档:
data
是MutexGuard<usize>
,因此请检查MutexGuard<T>
。*data
是需要变异的上下文中的指针解除引用。寻找DerefMut
。MutexGuard<T>
,它实现了DerefMut::deref_mut(&mut self) -> &mut T
。*data
的结果为&mut usize
。然后我们有你修改过的例子。在这一点上,应该很清楚,完全没有做同样的事情:它正在改变一个碰巧包含与互斥锁相同值的局部变量。但因为它是局部变量,所以更改它绝对不会影响互斥锁的内容。
因此,短版本是:锁定互斥锁的结果是包装实际值的“智能指针”,而不是值本身。因此,您必须取消引用它才能访问该值。