混淆 Arc 的自动取消引用 [英] Confusing automatic dereferencing of Arc

查看:40
本文介绍了混淆 Arc 的自动取消引用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是取自 Mutex文档:

This is an example taken from the 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 注释在哪里.它被指定为

My question is where the snippet comment is. It is given as

let mut data = data.lock().unwrap();
*data += 1;
if *data == N {
    tx.send(()).unwrap();
}

数据的类型是Arc>,所以在调用data.lock()时,我假设Arccode> 被自动取消引用,并且 usize 被分配给 data.为什么我们需要在 data 前面再次使用 * 来取消引用它?

The type of data is Arc<Mutex<usize>>, so when calling data.lock(), I assumed that the Arc is being automatically dereferenced and an usize is assigned to data. Why do we need a *in front of data again to dereference it?

以下代码首先取消对 Arc 的引用,然后仅使用 usize 继续执行,也可以代替代码段.

The following code which first dereferences the Arc and then proceeds with just an usize also works in place of the snippet.

let mut data = *data.lock().unwrap();
data += 1;
if data == N {
    tx.send(()).unwrap();
}   

推荐答案

按照文档进行操作.从 Arc 开始:

Follow the docs. Starting with Arc<T>:

  • Arc::lock 是否存在?否.检查Deref.
  • Deref::TargetT.检查 Mutex.
  • Mutex::lock 是否存在?是的.它返回 LockResult>.
  • unwrap 来自哪里?LockResult 是一个Result> 的同义词.所以它是 Result::unwrap,结果是一个 MutexGuard.
  • 因此,data 属于 MutexGuard 类型.
  • Does Arc::lock exist? No. Check Deref.
  • Deref::Target is T. Check Mutex<T>.
  • Does Mutex::lock exist? Yes. It returns LockResult<MutexGuard<T>>.
  • Where does unwrap come from? LockResult<T> is a synonym for Result<T, PoisonError<T>>. So it's Result::unwrap, which results in a MutexGuard<T>.
  • Therefore, data is of type MutexGuard<usize>.

所以这是错误的:

所以在调用 data.lock() 时,我假设 Arc 被自动取消引用,并且 usize 被分配给 数据.

so when calling data.lock(), I assumed that the Arc is being automatically dereferenced and an usize is assigned to data.

因此问题不是为什么不能直接赋值,而是你如何能够分配usize.再次遵循文档:

Thus the question is not why you can't assign directly, but how you're able to assign an usize value at all. Again, follow the docs:

  • data 是一个 MutexGuard,因此请检查 MutexGuard.
  • *data 是需要突变的上下文中的指针取消引用.寻找 DerefMut 的实现.
  • 它说对于 MutexGuard,它实现了 DerefMut::deref_mut(&mut self) ->&mut T.
  • 因此,*data 的结果是 &mut usize.
  • data is a MutexGuard<usize>, so check MutexGuard<T>.
  • *data is a pointer dereference in a context that requires mutation. Look for an implementation of DerefMut.
  • It says that for MutexGuard<T>, it implements DerefMut::deref_mut(&mut self) -> &mut T.
  • Thus, the result of *data is &mut usize.

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

Then we have your modified example. At this point, it should be clear that this is not at all doing the same thing: it's mutating a local variable that happens to contain the same value as the mutex. But because it's a local variable, changing it has absolutely no bearing on the contents of the mutex.

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

Thus, the short version is: the result of locking a mutex is a "smart pointer" wrapping the actual value, not the value itself. Thus you have to dereference it to access the value.

这篇关于混淆 Arc 的自动取消引用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆