在异步函数的匹配中获取死锁
Getting deadlock inside match of async function
我在以下示例中陷入僵局:
use tokio::net::TcpListener;
use tokio::io::{AsyncReadExt, AsyncWriteExt};
use futures::lock::Mutex;
use std::sync::Arc;
struct A{
}
impl A {
pub async fn do_something(&self) -> std::result::Result<(), ()>{
Err(())
}
}
async fn lock_and_use(a: Arc<Mutex<A>>) {
match a.clone().lock().await.do_something().await {
Ok(()) => {
},
Err(()) => {
//try again on error
println!("trying again");
a.clone().lock().await.do_something().await.unwrap();
}
}
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("begin");
let a = Arc::new(Mutex::new(A{}));
lock_and_use(a.clone()).await;
println!("end");
Ok(())
}
如果我这样做:
a.clone().lock().await.do_something().await;
a.clone().lock().await.do_something().await;
不会有问题,lock()
在它创建的同一行死掉。我认为这个原则对于 match
也是一样的。如果您考虑 match,它会锁定值,在其上调用 do_something
、await
s,然后比较值。确实do_something
returns一个future里面捕获了self
,但是当我们await
放在上面的时候,它应该丢弃self
。为什么它仍然成立 self
?如何在不克隆结果的情况下解决这个问题?
是:
Temporaries live for the entire statement, never shorter.
原因代码可能是:
{
match self.cache.read() { // <-- direct pattern matching
Ok(ref data) => Some(data)
_ => None,
}
}.map(|data| {
// use `data` - the lock better be held
})
阅读 this issue 了解更多详情。
因此您需要在 match 语句之外锁定:
let x = a.clone().lock().await.do_something().await;
match x {
Ok(()) => {}
Err(()) => {
a.clone().lock().await.do_something().await.unwrap();
}
}
我在以下示例中陷入僵局:
use tokio::net::TcpListener;
use tokio::io::{AsyncReadExt, AsyncWriteExt};
use futures::lock::Mutex;
use std::sync::Arc;
struct A{
}
impl A {
pub async fn do_something(&self) -> std::result::Result<(), ()>{
Err(())
}
}
async fn lock_and_use(a: Arc<Mutex<A>>) {
match a.clone().lock().await.do_something().await {
Ok(()) => {
},
Err(()) => {
//try again on error
println!("trying again");
a.clone().lock().await.do_something().await.unwrap();
}
}
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("begin");
let a = Arc::new(Mutex::new(A{}));
lock_and_use(a.clone()).await;
println!("end");
Ok(())
}
如果我这样做:
a.clone().lock().await.do_something().await;
a.clone().lock().await.do_something().await;
不会有问题,lock()
在它创建的同一行死掉。我认为这个原则对于 match
也是一样的。如果您考虑 match,它会锁定值,在其上调用 do_something
、await
s,然后比较值。确实do_something
returns一个future里面捕获了self
,但是当我们await
放在上面的时候,它应该丢弃self
。为什么它仍然成立 self
?如何在不克隆结果的情况下解决这个问题?
是:
Temporaries live for the entire statement, never shorter.
原因代码可能是:
{
match self.cache.read() { // <-- direct pattern matching
Ok(ref data) => Some(data)
_ => None,
}
}.map(|data| {
// use `data` - the lock better be held
})
阅读 this issue 了解更多详情。
因此您需要在 match 语句之外锁定:
let x = a.clone().lock().await.do_something().await;
match x {
Ok(()) => {}
Err(()) => {
a.clone().lock().await.do_something().await.unwrap();
}
}