我正在调用一个异步实现的方法:
let mut safebrowsing: MutexGuard<Safebrowsing> = self.safebrowsing.lock().unwrap();
safebrowsing.is_safe(input: &message.content).await;
是安全的方法:
pub async fn is_safe(&mut self, input: &str) {
let links = self.finder.links(input);
for link in links {
match reqwest::get("url").await {
Ok(response) => {
println!(
"{}",
response.text().await.expect("response has no content")
);
}
Err(_) => {
println!("Unable to get safebrowsing-response")
}
}
}
}
但不幸的是,通过异步调用is_safe-方法,编译器告诉我线程无法安全发送。错误如下:
future cannot be sent between threads safely
within `impl std::future::Future`, the trait `std::marker::Send` is not implemented for `std::sync::MutexGuard<'_, Safebrowsing>`
required for the cast to the object type `dyn std::future::Future<Output = ()> + std::marker::Send`
handler.rs(31, 9): future is not `Send` as this value is used across an await
^-- safebrowsing.is_safe(input: &message.content).await;
---
future cannot be sent between threads safely
the trait `std::marker::Send` is not implemented for `(dyn for<'r> Fn(&'r [u8]) -> Option<usize> + 'static)`
required for the cast to the object type `dyn std::future::Future<Output = ()> + std::marker::Send`
safebrowsing.rs(22, 19): future is not `Send` as this value is used across an await
^-- match reqwest::get("url").await
我已经试着在Safebrowsing-Struct中实现了Send-Trait,但是同样不起作用。我需要做些什么来让它起作用吗?因为我不知道为什么会出现这种情况
2条答案
按热度按时间gab6jxml1#
这个错误的关键是
MutexGuard<T>
不是Send
,这意味着你试图在互斥锁被锁定时执行await
,如果你仔细想想,这通常是个坏主意:原则上,await
可以无限期地等待,但是如果在互斥锁保持的情况下等待太长时间,任何其他试图锁定互斥锁的线程都会阻塞,也是无限期地阻塞(当然,除非您设置了超时)。因此,作为一条经验法则,你不应该在互斥锁被锁定的情况下睡觉,例如你的代码可以被重写为(完全未经测试):
如果你需要在函数的后面锁定
Mutex
,小心竞争!它可能已经被其他线程修改了,也许那个input
已经不存在了。b5buobof2#
使用您正在使用的异步运行时中的Mutex实现。
使用mutex from standard library:
使用mutex from tokio:
"但为什么"
粗略地说,本机互斥锁强制锁保持在同一个线程中,但异步运行时不理解它。
如果您的锁不与
async
交叉,那么您可以使用stdlib中的互斥锁(这样会更快)。参见tokio documentation中的讨论。