如何为具有动态成员的结构采用 Send 和 Sync(未来不能在线程之间安全地发送)
How to adopt Send and Sync for a struct with a dynamic member (future cannot be sent between threads safely)
考虑以下代码,它使用 async-trait
板条箱使用 async
方法声明特征。
use std::{io::Result, sync::Arc};
use async_trait::async_trait;
use tokio;
// A trait that describes a power source.
trait PowerSource {
fn supply_power(&self) -> Result<()>;
}
// ElectricMotor implements PowerSource.
struct ElectricMotor {}
impl PowerSource for ElectricMotor {
fn supply_power(&self) -> Result<()> {
println!("ElectricMotor::supply_power");
Ok(())
}
}
// A trait that describes a vehicle
#[async_trait]
trait Vehicle {
async fn drive(&self) -> Result<()>;
}
// An automobile has some kind of power source and implements Vehicle
struct Automobile {
power_source: Arc<dyn PowerSource>,
}
#[async_trait]
impl Vehicle for Automobile {
async fn drive(&self) -> Result<()> {
self.power_source.supply_power()?;
println!("Vehicle::Drive");
Ok(())
}
}
#[tokio::main]
async fn main() -> std::io::Result<()> {
let driver = ElectricMotor {};
let controller = Automobile {
power_source: Arc::new(driver),
};
controller.drive().await?;
Ok(())
}
这不会编译并出现错误“未来无法在线程之间安全发送”:
error: future cannot be sent between threads safely
--> src/main.rs:34:41
|
34 | async fn drive(&self) -> Result<()> {
| _________________________________________^
35 | | self.power_source.supply_power()?;
36 | | println!("Vehicle::Drive");
37 | | Ok(())
38 | | }
| |_____^ future created by async block is not `Send`
|
= help: the trait `Sync` is not implemented for `(dyn PowerSource + 'static)`
note: captured value is not `Send`
--> src/main.rs:34:21
|
34 | async fn drive(&self) -> Result<()> {
| ^^^^ has type `&Automobile` which is not `Send`
= note: required for the cast to the object type `dyn Future<Output = Result<(), std::io::Error>> + Send`
error: future cannot be sent between threads safely
--> src/main.rs:34:41
|
34 | async fn drive(&self) -> Result<()> {
| _________________________________________^
35 | | self.power_source.supply_power()?;
36 | | println!("Vehicle::Drive");
37 | | Ok(())
38 | | }
| |_____^ future created by async block is not `Send`
|
= help: the trait `Send` is not implemented for `(dyn PowerSource + 'static)`
note: captured value is not `Send`
--> src/main.rs:34:21
|
34 | async fn drive(&self) -> Result<()> {
| ^^^^ has type `&Automobile` which is not `Send`
= note: required for the cast to the object type `dyn Future<Output = Result<(), std::io::Error>> + Send`
如果我理解错误的话,它认为 Automobile
不是 Send
因为 power_source
属性 不是所以它不能创建一个合适的未来。我的理解是 Arc
是线程安全的并且实现了 Send
和 Sync
,但我对 Rust 并发仍然很陌生,仍然不完全清楚这意味着什么。
我该如何解决这个错误?
您必须修改您的 Automobile
定义:
struct Automobile {
power_source: Arc<dyn PowerSource>,
}
在 Rust 中,一个类型是 Send
当且仅当它的所有成员都是 Send
(除非你手动且不安全地实现 Send
)。这同样适用于 Sync
。所以假设你的 power_source
不是 Send
,那么生成的 impl Future
也不会是 Send
.
The way to fix it is to add a Send + Sync
requirement for power_source
:
struct Automobile {
power_source: Arc<dyn PowerSource + Send + Sync>,
}
但是为什么 Sync
您可能会问?毕竟编译器只抱怨 Send
。它需要 Sync
的原因是因为 Arc<T>
implements Send
only if T
is both Send
and Sync
补充阅读:
考虑以下代码,它使用 async-trait
板条箱使用 async
方法声明特征。
use std::{io::Result, sync::Arc};
use async_trait::async_trait;
use tokio;
// A trait that describes a power source.
trait PowerSource {
fn supply_power(&self) -> Result<()>;
}
// ElectricMotor implements PowerSource.
struct ElectricMotor {}
impl PowerSource for ElectricMotor {
fn supply_power(&self) -> Result<()> {
println!("ElectricMotor::supply_power");
Ok(())
}
}
// A trait that describes a vehicle
#[async_trait]
trait Vehicle {
async fn drive(&self) -> Result<()>;
}
// An automobile has some kind of power source and implements Vehicle
struct Automobile {
power_source: Arc<dyn PowerSource>,
}
#[async_trait]
impl Vehicle for Automobile {
async fn drive(&self) -> Result<()> {
self.power_source.supply_power()?;
println!("Vehicle::Drive");
Ok(())
}
}
#[tokio::main]
async fn main() -> std::io::Result<()> {
let driver = ElectricMotor {};
let controller = Automobile {
power_source: Arc::new(driver),
};
controller.drive().await?;
Ok(())
}
这不会编译并出现错误“未来无法在线程之间安全发送”:
error: future cannot be sent between threads safely
--> src/main.rs:34:41
|
34 | async fn drive(&self) -> Result<()> {
| _________________________________________^
35 | | self.power_source.supply_power()?;
36 | | println!("Vehicle::Drive");
37 | | Ok(())
38 | | }
| |_____^ future created by async block is not `Send`
|
= help: the trait `Sync` is not implemented for `(dyn PowerSource + 'static)`
note: captured value is not `Send`
--> src/main.rs:34:21
|
34 | async fn drive(&self) -> Result<()> {
| ^^^^ has type `&Automobile` which is not `Send`
= note: required for the cast to the object type `dyn Future<Output = Result<(), std::io::Error>> + Send`
error: future cannot be sent between threads safely
--> src/main.rs:34:41
|
34 | async fn drive(&self) -> Result<()> {
| _________________________________________^
35 | | self.power_source.supply_power()?;
36 | | println!("Vehicle::Drive");
37 | | Ok(())
38 | | }
| |_____^ future created by async block is not `Send`
|
= help: the trait `Send` is not implemented for `(dyn PowerSource + 'static)`
note: captured value is not `Send`
--> src/main.rs:34:21
|
34 | async fn drive(&self) -> Result<()> {
| ^^^^ has type `&Automobile` which is not `Send`
= note: required for the cast to the object type `dyn Future<Output = Result<(), std::io::Error>> + Send`
如果我理解错误的话,它认为 Automobile
不是 Send
因为 power_source
属性 不是所以它不能创建一个合适的未来。我的理解是 Arc
是线程安全的并且实现了 Send
和 Sync
,但我对 Rust 并发仍然很陌生,仍然不完全清楚这意味着什么。
我该如何解决这个错误?
您必须修改您的 Automobile
定义:
struct Automobile {
power_source: Arc<dyn PowerSource>,
}
在 Rust 中,一个类型是 Send
当且仅当它的所有成员都是 Send
(除非你手动且不安全地实现 Send
)。这同样适用于 Sync
。所以假设你的 power_source
不是 Send
,那么生成的 impl Future
也不会是 Send
.
The way to fix it is to add a Send + Sync
requirement for power_source
:
struct Automobile {
power_source: Arc<dyn PowerSource + Send + Sync>,
}
但是为什么 Sync
您可能会问?毕竟编译器只抱怨 Send
。它需要 Sync
的原因是因为 Arc<T>
implements Send
only if T
is both Send
and Sync