我在理解如何修改互斥体中的Option时遇到了问题。
当没有选项时,它工作得很好
let mut my_int = Arc::new(Mutex::new(5));
let my_int_clone = Arc::clone(&my_int);
thread::spawn(move || {
let mut my_int = my_int_clone.lock().unwrap();
*my_int += 1;
}).join();
let my_int_clone_print = Arc::clone(&my_int);
println!("Value: {}", my_int_clone_print.lock().unwrap());
然而,当我将值 Package 在Some
中时,我不得不手动使用ref mut
等(我从here中找到了它),因为lock().unwrap()
返回MutexGuard
,而不是Option
本身。
let mut my_int = Arc::new(Mutex::new(Some(5)));
let my_int_clone = Arc::clone(&my_int);
thread::spawn(move || {
let mut my_int = my_int_clone.lock().unwrap();
match *my_int {
Some(ref mut val) => {
*val += 1;
},
None => {
println!("Value is None. Doing nothing..");
}
}
}).join();
let my_int_clone_print = Arc::clone(&my_int);
println!("Value: {}", my_int_clone_print.lock().unwrap());
你知道是哪个Rust概念导致的吗?除了Option
之外,还有其他数据类型返回MutexGuard
而不是它的原始值吗?
2条答案
按热度按时间biswetbf1#
实际上,
Mutex::lock
在两种情况下都返回Result<MutexGuard, ..>
。不过,这种类型有有趣的trait实现:Deref
和DerefMut
。它们允许通过*
运算符显式解引用。考虑以下显式类型的示例:当然,你也可以类似地使用
Option
:注意,最后一个匹配示例与您的示例完全相同,但使用的语法略有不同。
hjzp0vay2#
除了返回
MutexGuard
而不是其原始值的Option
之外,还有其他数据类型吗?MutexGuard
不能返回原始值,因为移动值会使互斥体无效。相反,它是一个 Package 器,提供了一个对原始值的可变 * 引用 *。这并不是特定于
Option
,MutexGuard
是Mutex::lock
总是返回的。例如,以下代码:...将报告
m.lock().unwrap()
返回的类型是std::sync::MutexGuard<'_, bool>
。MutexGuard
在引用没有超过保护的条件下给出对数据的访问。*my_int += 1
工作是因为MutexGuard
实现了DerefMut
,它告诉*
操作符要处理什么引用。*
操作符在Option
上工作得很好;例如:匹配
*my_int
可以在没有ref mut
的情况下完成,但*my_int
将复制该选项(只要它的内容是Copy
,它就可以工作),修改该值对选项本身没有影响。这也不是特定于MutexGuard
的,这就是匹配的工作方式。ref mut
是为您提供对选项内数据的可变访问所必需的。