gpt4 book ai didi

rust - 异步函数 : the trait `std::marker::Send` is not implemented for `std::sync::MutexGuard<' _, 客户端>`

转载 作者:行者123 更新时间:2023-12-04 12:04:48 31 4
gpt4 key购买 nike

我在异步中使用递归时遇到了一个奇怪的错误。
我可以用 clientasync .但是,如果我拨打 do_something它再次提示 std::sync::MutexGuard<'_, Client>没有被发送。我认为它正在尝试发送 c到另一个线程。我以为do_something在一个线程中执行,和 do_something(client.clone()).await在另一个。我不明白为什么c正在搬离async线程到这个新线程。

use std::sync::{Arc, Mutex};
use std::future::Future;
use futures::future::{BoxFuture, FutureExt};

struct Client{
}

impl Client {}

fn do_something<'a>(
client: Arc<Mutex<Client>>,
) -> BoxFuture<'a, std::result::Result<(), ()>> {
async move {
let c = client.lock().unwrap();
do_something(client.clone()).await;
Ok(())
}.boxed()
}

fn main() {
let c = Arc::new(Mutex::new(Client{}));
do_something(c.clone());
}
错误:
error: future cannot be sent between threads safely
--> src/main.rs:17:7
|
17 | }.boxed()
| ^^^^^ future created by async block is not `Send`
|
= help: within `impl futures::Future`, the trait `std::marker::Send` is not implemented for `std::sync::MutexGuard<'_, Client>`
note: future is not `Send` as this value is used across an await
--> src/main.rs:15:9
|
14 | let c = client.lock().unwrap();
| - has type `std::sync::MutexGuard<'_, Client>` which is not `Send`
15 | do_something(client.clone()).await;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ await occurs here, with `c` maybe used later
16 | Ok(())
17 | }.boxed()
| - `c` is later dropped here
Playground

最佳答案

这里有两个问题,都源于标准库 Mutex旨在与常规阻塞代码一起使用,而不是异步代码:

  • 锁定互斥量会阻塞线程,这通常是您希望在异步代码中避免的,因为它可以阻止其他任务运行。
  • 正如编译器错误中所见,通过锁定它获得的互斥锁不能在线程之间安全地共享,因此无论如何它都不会编译。

  • 这两个问题都可以通过使用 Mutex 来解决。专为异步代码设计。因为你已经在使用 futures 中的东西了crate,你可以使用 futures::lock::Mutex , 改变 client.lock().unwrap()client.lock().await .当需要等待而不是阻塞线程时,此版本的锁会将控制权交还给任务执行器,并且还允许在必要时在线程之间共享它。
    代码的完整版本看起来像这样 - 但是,它不是很有用,因为您实际上从未真正执行 do_something 返回的 future 。 (请注意,您没有对返回的 future 做任何事情),即使您做了,由于递归,它会立即陷入僵局:
    use std::sync::Arc;
    use std::future::Future;
    use futures::future::{BoxFuture, FutureExt};
    use futures::lock::Mutex;

    struct Client {}

    impl Client {}

    fn do_something<'a>(
    client: Arc<Mutex<Client>>,
    ) -> BoxFuture<'a, std::result::Result<(), ()>> {
    async move {
    let c = client.lock().await;
    do_something(client.clone()).await;
    Ok(())
    }.boxed()
    }

    fn main() {
    let c = Arc::new(Mutex::new(Client {}));
    do_something(c.clone());
    }
    Playground

    关于rust - 异步函数 : the trait `std::marker::Send` is not implemented for `std::sync::MutexGuard<' _, 客户端>`,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67277282/

    31 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com