簡體   English   中英

Rust 從互斥鎖訪問選項

[英]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 實現: DerefDerefMut 這些允許通過*運算符顯式取消引用。 考慮這個帶有顯式類型的例子:

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的, MutexGuardMutex::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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM