gpt4 book ai didi

multithreading - 为什么不为包含Arc的结构实现Send?

转载 作者:行者123 更新时间:2023-12-03 11:45:06 25 4
gpt4 key购买 nike

我正在使用a crate与Postgres进行交互,只需手动编写sql查询(对于我的简单情况,Diesel似乎很简单),并且陷入了对数据库客户端的多线程访问的困境。这是代码:

use postgres::Client;

pub struct Database{
connection: Arc<Client>
}

impl Database {
pub fn from_config(url: &str) -> Database {
//...
}
}

fn main() {
let url: String = //...
let db = db::Database::from_config(&url);
let db_ref = Arc::new(db);
consume(future(Arc::clone(&db_ref))); // <------------------- compile error
}

async fn future(db_ref: Arc<db::Database>){ }

fn consume<F>(f: F)
where F: Send{ }
postgres::Client 定义为
/// A synchronous PostgreSQL client.
pub struct Client {
connection: Connection,
client: tokio_postgres::Client,
}
编译此代码时,编译时我得到了一些疯狂的错误消息:
error[E0277]: `(dyn futures_core::stream::Stream<Item = std::result::Result<tokio_postgres::AsyncMessage, tokio_postgres::error::Error>> + std::marker::Send + 'static)` cannot be shared between threads safely
--> src/main.rs:17:5
|
17 | consume(future(Arc::clone(&db_ref)));
| ^^^^^^^ `(dyn futures_core::stream::Stream<Item = std::result::Result<tokio_postgres::AsyncMessage, tokio_postgres::error::Error>> + std::marker::Send + 'static)` cannot be shared between threads safely
...
24 | fn consume<F>(f: F)
| ------- required by a bound in this
25 | where F: Send{ }
| ---- required by this bound in `consume`
|
= help: the trait `std::marker::Sync` is not implemented for `(dyn futures_core::stream::Stream<Item = std::result::Result<tokio_postgres::AsyncMessage, tokio_postgres::error::Error>> + std::marker::Send + 'static)`
= note: required because of the requirements on the impl of `std::marker::Sync` for `std::ptr::Unique<(dyn futures_core::stream::Stream<Item = std::result::Result<tokio_postgres::AsyncMessage, tokio_postgres::error::Error>> + std::marker::Send + 'static)>`
= note: required because it appears within the type `std::boxed::Box<(dyn futures_core::stream::Stream<Item = std::result::Result<tokio_postgres::AsyncMessage, tokio_postgres::error::Error>> + std::marker::Send + 'static)>`
= note: required because it appears within the type `std::pin::Pin<std::boxed::Box<(dyn futures_core::stream::Stream<Item = std::result::Result<tokio_postgres::AsyncMessage, tokio_postgres::error::Error>> + std::marker::Send + 'static)>>`
= note: required because it appears within the type `postgres::connection::Connection`
= note: required because it appears within the type `postgres::client::Client`
= note: required because of the requirements on the impl of `std::marker::Send` for `std::sync::Arc<postgres::client::Client>`
= note: required because it appears within the type `db::Database`
= note: required because of the requirements on the impl of `std::marker::Send` for `std::sync::Arc<db::Database>`
= note: required because it appears within the type `[static generator@src/main.rs:22:43: 22:46 db_ref:std::sync::Arc<db::Database> {}]`
= note: required because it appears within the type `std::future::from_generator::GenFuture<[static generator@src/main.rs:22:43: 22:46 db_ref:std::sync::Arc<db::Database> {}]>`
= note: required because it appears within the type `impl core::future::future::Future`
= note: required because it appears within the type `impl core::future::future::Future`
这似乎意味着 Database没有实现 Send。有没有一种方法可以实现 Send?也许应该使用 Mutex或其他方式代替 Arc吗?
UPD:
用替换结构定义
pub struct Database{
connection: Mutex<Client>
}
使错误消失,但原因尚不清楚...

最佳答案

Arc<T>允许多个线程同时访问相同的值。 Sync特性可以验证访问不会导致内存不安全,因此Arc为什么需要它。
另一方面,Mutex<T>通过锁定控制对T的访问,因此一次只有一个线程可以访问T(在某种意义上,将其“发送”到具有锁的线程中)。因此,即使Mutex<T>不是,Sync也就是T(尽管它仍然必须是Send)。
但是,Mutex<T>本身并没有用,因为无论如何只有一个线程可以访问该互斥量。您通常将其与共享所有权的方式(即Arc)结合使用,以允许多个线程访问互斥量。

关于multithreading - 为什么不为包含Arc的结构实现Send?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63144311/

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