令人困惑的Arc自动解除引用

Ara*_*h S 1 rust

这是从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::TargetT.检查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.

然后我们有你修改过的例子.在这一点上,应该清楚的是,这根本不做同样的事情:它正在改变一个碰巧包含与互斥量相同的值的局部变量.但由于它是局部变量,因此更改它对互斥锁的内容完全没有影响.


因此,短版本是:锁定互斥锁的结果是包装实际值的"智能指针",而不是值本身.因此,您必须取消引用它才能访问该值.