混淆 Arc 的自动取消引用 [英] Confusing automatic dereferencing of 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()
时,我假设Arc
code> 被自动取消引用,并且 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::Target
是T
.检查Mutex
.Mutex::lock
是否存在?是的.它返回LockResult
.> unwrap
来自哪里?LockResult
是一个Result
的同义词.所以它是> Result::unwrap
,结果是一个MutexGuard
.- 因此,
data
属于MutexGuard
类型.
- Does
Arc::lock
exist? No. CheckDeref
. Deref::Target
isT
. CheckMutex<T>
.- Does
Mutex::lock
exist? Yes. It returnsLockResult<MutexGuard<T>>
. - Where does
unwrap
come from?LockResult<T>
is a synonym forResult<T, PoisonError<T>>
. So it'sResult::unwrap
, which results in aMutexGuard<T>
. - Therefore,
data
is of typeMutexGuard<usize>
.
所以这是错误的:
所以在调用 data.lock()
时,我假设 Arc
被自动取消引用,并且 usize
被分配给 数据代码>.
so when calling
data.lock()
, I assumed that theArc
is being automatically dereferenced and anusize
is assigned todata
.
因此问题不是为什么不能直接赋值,而是你如何能够分配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 aMutexGuard<usize>
, so checkMutexGuard<T>
.*data
is a pointer dereference in a context that requires mutation. Look for an implementation ofDerefMut
.- It says that for
MutexGuard<T>
, it implementsDerefMut::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屋!