Rust 从互斥体访问 Option
Rust accessing Option from mutex
我无法理解如何修改 Mutex 中的选项。
没有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());
但是,当我将值包装在 Some
中时,我不得不手动使用 ref mut
等(我从 here 中找到它)因为 lock().unwrap()
returns 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
returns MutexGuard
而不是其原始值之外还有其他数据类型吗?
实际上,Mutex::lock
returns Result<MutexGuard, ..>
in both cases. Though, this type has interesting trait implementation: Deref
and DerefMut
。这些允许通过 *
运算符显式取消引用。考虑这个带有显式类型的例子:
let mutex = Mutex::new(1i32);
let mut guard: MutexGuard<'_, i32> = mutex.lock().unwrap();
// This dereferences to &mut i32
// because assignment operator works with &mut self.
*guard = 2;
// Nevertheless, for an explicit borrowing you need &mut
// because otherwise it would be moved from the guard.
let inner: &mut i32 = &mut *guard;
当然,您也可以类似地使用 Option
:
let mutex = Mutex::new(Some(1i32));
let mut guard: MutexGuard<'_, Option<i32>> = mutex.lock().unwrap();
// Directly change inner value
*guard = Some(2);
// or use in match, notice &mut borrowing
match &mut *guard {
Some(x) => *x += 1,
None => {},
}
注意,最后一个匹配示例与您的示例完全相同,但语法略有不同。 Playground.
there any more data types besides Option
which returns MutexGuard
and not its original value?
MutexGuard
不能 return 原始值,因为移动该值会使互斥量无效。相反,它是一个包装器,提供对原始值的可变 reference。
这绝不是 Option
特有的,MutexGuard
是 Mutex::lock
总是 return 的。例如,这段代码:
let m = Mutex::<bool>::new(false);
let () = m.lock().unwrap();
...会抱怨 m.lock().unwrap()
编辑的 return 类型是 std::sync::MutexGuard<'_, bool>
.
MutexGuard
在引用不超过守卫的条件下给出对数据的访问。 *my_int += 1
有效是因为 MutexGuard
实现了 DerefMut
,它告诉 *
运算符要处理的引用。 *
运算符与 Option
完美配合;例如:
let m = Mutex::<Option<i32>>::new(Some(0));
let mut my_int = m.lock().unwrap();
*my_int = Some(100);
匹配 *my_int
可以在没有 ref mut
的情况下完成,但是 *my_int
将复制选项(只要其内容为 Copy
就可以工作)并修改该值对选项本身没有影响。这也绝不是 MutexGuard
特有的,这就是匹配的工作原理。需要 ref mut
才能让您可变访问选项内的数据。
我无法理解如何修改 Mutex 中的选项。
没有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());
但是,当我将值包装在 Some
中时,我不得不手动使用 ref mut
等(我从 here 中找到它)因为 lock().unwrap()
returns 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
returns MutexGuard
而不是其原始值之外还有其他数据类型吗?
实际上,Mutex::lock
returns Result<MutexGuard, ..>
in both cases. Though, this type has interesting trait implementation: Deref
and DerefMut
。这些允许通过 *
运算符显式取消引用。考虑这个带有显式类型的例子:
let mutex = Mutex::new(1i32);
let mut guard: MutexGuard<'_, i32> = mutex.lock().unwrap();
// This dereferences to &mut i32
// because assignment operator works with &mut self.
*guard = 2;
// Nevertheless, for an explicit borrowing you need &mut
// because otherwise it would be moved from the guard.
let inner: &mut i32 = &mut *guard;
当然,您也可以类似地使用 Option
:
let mutex = Mutex::new(Some(1i32));
let mut guard: MutexGuard<'_, Option<i32>> = mutex.lock().unwrap();
// Directly change inner value
*guard = Some(2);
// or use in match, notice &mut borrowing
match &mut *guard {
Some(x) => *x += 1,
None => {},
}
注意,最后一个匹配示例与您的示例完全相同,但语法略有不同。 Playground.
there any more data types besides
Option
which returnsMutexGuard
and not its original value?
MutexGuard
不能 return 原始值,因为移动该值会使互斥量无效。相反,它是一个包装器,提供对原始值的可变 reference。
这绝不是 Option
特有的,MutexGuard
是 Mutex::lock
总是 return 的。例如,这段代码:
let m = Mutex::<bool>::new(false);
let () = m.lock().unwrap();
...会抱怨 m.lock().unwrap()
编辑的 return 类型是 std::sync::MutexGuard<'_, bool>
.
MutexGuard
在引用不超过守卫的条件下给出对数据的访问。 *my_int += 1
有效是因为 MutexGuard
实现了 DerefMut
,它告诉 *
运算符要处理的引用。 *
运算符与 Option
完美配合;例如:
let m = Mutex::<Option<i32>>::new(Some(0));
let mut my_int = m.lock().unwrap();
*my_int = Some(100);
匹配 *my_int
可以在没有 ref mut
的情况下完成,但是 *my_int
将复制选项(只要其内容为 Copy
就可以工作)并修改该值对选项本身没有影响。这也绝不是 MutexGuard
特有的,这就是匹配的工作原理。需要 ref mut
才能让您可变访问选项内的数据。