Rud*_*dog 3 concurrency asynchronous rust
考虑下面的代码,它async
使用async-trait
crate 的方法声明了一个特征。
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(())
}
Run Code Online (Sandbox Code Playgroud)
这不会编译错误“未来无法在线程之间安全地发送”:
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`
Run Code Online (Sandbox Code Playgroud)
如果我正确理解错误,它认为这Automobile
不是Send
因为该power_source
财产不是,所以它不能创造一个适当的未来。我的理解是它Arc
是线程安全的并且实现了Send
and Sync
,但我对 Rust 并发性仍然很陌生,并且仍然不完全清楚这意味着什么。
我该如何修复这个错误?
Sve*_*rev 14
您必须修改您的Automobile
定义:
struct Automobile {
power_source: Arc<dyn PowerSource>,
}
Run Code Online (Sandbox Code Playgroud)
在 Rust 中,类型Send
当且仅当其所有成员都是Send
(除非您手动且不安全地实现Send
)。这同样适用于Sync
. 因此,鉴于您的power_source
不是Send
,那么生成的impl Future
也将不是Send
。
修复它的方法是添加Send + Sync
以下要求power_source
:
struct Automobile {
power_source: Arc<dyn PowerSource + Send + Sync>,
}
Run Code Online (Sandbox Code Playgroud)
但Sync
你可能会问为什么?Send
毕竟编译器只是在抱怨。它需要的原因Sync
是因为Arc<T>
只有Send
当T
是Send
并且 Sync