为什么不为包含 Arc 的结构实现 Send?
Why isnt Send implemented for a struct containing Arc?
我正在使用 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{ }
/// 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
?
更新:
将结构定义替换为
pub struct Database{
connection: Mutex<Client>
}
使错误消失,但完全不清楚为什么...
原因是特征实现 Send for Arc
was defined as
impl<T> Send for Arc<T>
where
T: Send + Sync + ?Sized,
所以Sync
也需要实现。这就是错误消息所说的。对于Mutex
依次Send
is defined as
impl<T: ?Sized + Send> Send for Mutex<T>
不需要 Sync
实施。
Arc<T>
允许多个线程同时访问同一个值。 Sync
特征是验证访问不会导致内存不安全的原因,因此 Arc
需要它。
另一方面,Mutex<T>
通过锁定控制对T
的访问,因此一次只有一个线程可以访问T
(某种意义上,'sending' 它到具有锁的线程)。所以 Mutex<T>
是 Sync
即使 T
不是(尽管它仍然必须是 Send
)。
但是 Mutex<T>
本身并没有用,因为无论如何只有一个线程可以访问互斥量。您通常将它与共享所有权的方式(即 Arc
)相结合,以允许多个线程访问互斥锁。
我正在使用 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{ }
/// 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
?
更新:
将结构定义替换为
pub struct Database{
connection: Mutex<Client>
}
使错误消失,但完全不清楚为什么...
原因是特征实现 Send for Arc
was defined as
impl<T> Send for Arc<T>
where
T: Send + Sync + ?Sized,
所以Sync
也需要实现。这就是错误消息所说的。对于Mutex
依次Send
is defined as
impl<T: ?Sized + Send> Send for Mutex<T>
不需要 Sync
实施。
Arc<T>
允许多个线程同时访问同一个值。 Sync
特征是验证访问不会导致内存不安全的原因,因此 Arc
需要它。
另一方面,Mutex<T>
通过锁定控制对T
的访问,因此一次只有一个线程可以访问T
(某种意义上,'sending' 它到具有锁的线程)。所以 Mutex<T>
是 Sync
即使 T
不是(尽管它仍然必须是 Send
)。
但是 Mutex<T>
本身并没有用,因为无论如何只有一个线程可以访问互斥量。您通常将它与共享所有权的方式(即 Arc
)相结合,以允许多个线程访问互斥锁。