这是从Mutex文档中获取的示例:
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();
}
Run Code Online (Sandbox Code Playgroud)
我的问题是snippet评论的位置.它被给予
let mut data = data.lock().unwrap();
*data += 1;
if *data == N {
tx.send(()).unwrap();
}
Run Code Online (Sandbox Code Playgroud)
数据的类型是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();
}
Run Code Online (Sandbox Code Playgroud)
DK.*_*DK. 10
按照文档.从以下开始Arc<T>:
Arc::lock存在?不,检查Deref.Deref::Target是T.检查Mutex<T>.Mutex::lock存在? 是的.它回来了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.然后我们有你修改过的例子.在这一点上,应该清楚的是,这根本不做同样的事情:它正在改变一个碰巧包含与互斥量相同的值的局部变量.但由于它是局部变量,因此更改它对互斥锁的内容完全没有影响.
因此,短版本是:锁定互斥锁的结果是包装实际值的"智能指针",而不是值本身.因此,您必须取消引用它才能访问该值.