[英]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
等(我從 這里找到它),因為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 概念會導致這種情況嗎? 除了返回MutexGuard
而不是原始值的Option
之外,還有其他數據類型嗎?
實際上, Mutex::lock
在這兩種情況下都返回Result<MutexGuard, ..>
。 不過,這種類型有有趣的 trait 實現: Deref
和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 => {},
}
請注意,最后一個匹配示例與您的完全相同,但使用的語法略有不同。 游樂場。
除了返回
MutexGuard
而不是原始值的Option
之外,還有其他數據類型嗎?
MutexGuard
無法返回原始值,因為移動該值會使互斥鎖無效。 相反,它是一個提供對原始值的可變引用的包裝器。
這絕不是特定於Option
的, MutexGuard
是Mutex::lock
總是返回的。 例如,這段代碼:
let m = Mutex::<bool>::new(false);
let () = m.lock().unwrap();
...會抱怨m.lock().unwrap()
返回的類型是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
才能讓您對選項內的數據進行可變訪問。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.