如何从 Arc<Mutex<T>> 获取 T 的所有权?
How to take ownership of T from Arc<Mutex<T>>?
我想 return 来自受 Mutex
保护的函数的值,但无法理解如何正确执行。此代码不起作用:
use std::sync::{Arc, Mutex};
fn func() -> Result<(), String> {
let result_my = Arc::new(Mutex::new(Ok(())));
let result_his = result_my.clone();
let t = std::thread::spawn(move || {
let mut result = result_his.lock().unwrap();
*result = Err("something failed".to_string());
});
t.join().expect("Unable to join thread");
let guard = result_my.lock().unwrap();
*guard
}
fn main() {
println!("func() -> {:?}", func());
}
编译器抱怨:
error[E0507]: cannot move out of borrowed content
--> src/main.rs:16:5
|
16 | *guard
| ^^^^^^ cannot move out of borrowed content
您可以使用 mem::replace
通过将其替换为新值来转移可变引用的所有权。 (返回并移动旧值)
use std::sync::{Arc, Mutex};
use std::mem;
fn func() -> Result<(), String> {
let result_my = Arc::new(Mutex::new(Ok(())));
let result_his = result_my.clone();
let t = std::thread::spawn(move || {
let mut result = result_his.lock().unwrap();
*result = Err("something failed".to_string());
});
t.join();
let mut guard = result_my.lock().unwrap();
mem::replace(&mut guard, Ok(()))
}
fn main() {
println!("func() -> {:?}", func());
}
到目前为止我找到的最好的解决方案是将结果包装成一个Option
然后取出来:
fn func() -> Result<(), String> {
let result_my = Arc::new(Mutex::new(Some(Ok(()))));
let result_his = result_my.clone();
let t = std::thread::spawn(move || {
let mut result = result_his.lock().unwrap();
*result = Some(Err("something failed".to_string()));
});
t.join().expect("Unable to join thread");
let mut guard = result_my.lock().unwrap();
guard.take().unwrap()
}
似乎比好,因为不需要构造一个空的T
来交换,而且它可以防止多次提取。
在 Rust 1.15 中,您可以使用 Arc::try_unwrap
and Mutex::into_inner
:
use std::sync::{Arc, Mutex};
fn func() -> Result<(), String> {
let result_my = Arc::new(Mutex::new(Ok(())));
let result_thread = result_my.clone();
let t = std::thread::spawn(move || {
let mut result = result_thread.lock().unwrap();
*result = Err("something failed".to_string());
});
t.join().expect("Unable to join threads");
let lock = Arc::try_unwrap(result_my).expect("Lock still has multiple owners");
lock.into_inner().expect("Mutex cannot be locked")
}
fn main() {
println!("func() -> {:?}", func());
}
RwLock::into_inner
自 Rust 1.6 以来也存在。
我想 return 来自受 Mutex
保护的函数的值,但无法理解如何正确执行。此代码不起作用:
use std::sync::{Arc, Mutex};
fn func() -> Result<(), String> {
let result_my = Arc::new(Mutex::new(Ok(())));
let result_his = result_my.clone();
let t = std::thread::spawn(move || {
let mut result = result_his.lock().unwrap();
*result = Err("something failed".to_string());
});
t.join().expect("Unable to join thread");
let guard = result_my.lock().unwrap();
*guard
}
fn main() {
println!("func() -> {:?}", func());
}
编译器抱怨:
error[E0507]: cannot move out of borrowed content
--> src/main.rs:16:5
|
16 | *guard
| ^^^^^^ cannot move out of borrowed content
您可以使用 mem::replace
通过将其替换为新值来转移可变引用的所有权。 (返回并移动旧值)
use std::sync::{Arc, Mutex};
use std::mem;
fn func() -> Result<(), String> {
let result_my = Arc::new(Mutex::new(Ok(())));
let result_his = result_my.clone();
let t = std::thread::spawn(move || {
let mut result = result_his.lock().unwrap();
*result = Err("something failed".to_string());
});
t.join();
let mut guard = result_my.lock().unwrap();
mem::replace(&mut guard, Ok(()))
}
fn main() {
println!("func() -> {:?}", func());
}
到目前为止我找到的最好的解决方案是将结果包装成一个Option
然后取出来:
fn func() -> Result<(), String> {
let result_my = Arc::new(Mutex::new(Some(Ok(()))));
let result_his = result_my.clone();
let t = std::thread::spawn(move || {
let mut result = result_his.lock().unwrap();
*result = Some(Err("something failed".to_string()));
});
t.join().expect("Unable to join thread");
let mut guard = result_my.lock().unwrap();
guard.take().unwrap()
}
似乎比T
来交换,而且它可以防止多次提取。
在 Rust 1.15 中,您可以使用 Arc::try_unwrap
and Mutex::into_inner
:
use std::sync::{Arc, Mutex};
fn func() -> Result<(), String> {
let result_my = Arc::new(Mutex::new(Ok(())));
let result_thread = result_my.clone();
let t = std::thread::spawn(move || {
let mut result = result_thread.lock().unwrap();
*result = Err("something failed".to_string());
});
t.join().expect("Unable to join threads");
let lock = Arc::try_unwrap(result_my).expect("Lock still has multiple owners");
lock.into_inner().expect("Mutex cannot be locked")
}
fn main() {
println!("func() -> {:?}", func());
}
RwLock::into_inner
自 Rust 1.6 以来也存在。