问题描述
我有下面的代码.随着注释掉的部分,它的工作.当我取消注释部分时,它不再编译.
I have the code below. With the commented out parts, it's working. When I uncomment the parts it does not compile anymore.
如何调整注释部分使其工作,即我想让线程同时访问表达式树.
How can I adjust the commented parts to make them work, i.e., I want to make threads access the expression tree simultaneously.
当我尝试时,编译器从线程安全性错误开始.
When I try it, the compiler starts with errors about thread safeness.
我读过 Rust 的书,知道 C/C++,但还没有完全理解 Rust 的类型系统和语义.
I read the Rust book and know C/C++, but didn't understood everything about Rust type system and semantics yet.
use std::thread;
use std::sync::Arc;
pub trait Expr {
fn run(&self) -> i32;
}
pub struct ConstantExpr {
n: i32,
}
impl ConstantExpr {
pub fn new(n: i32) -> Self {
Self { n }
}
}
impl Expr for ConstantExpr {
fn run(&self) -> i32 {
self.n
}
}
pub struct AddExpr {
expr1: Box<Expr>,
expr2: Box<Expr>,
}
impl AddExpr {
pub fn new(expr1: Box<Expr>, expr2: Box<Expr>) -> Self {
Self { expr1, expr2 }
}
}
impl Expr for AddExpr {
fn run(&self) -> i32 {
self.expr1.run() + self.expr2.run()
}
}
struct Container {
x: i32,
cached_expr: Arc<Expr>,
}
impl Container {
fn new() -> Self {
Self {
x: 0,
cached_expr: Arc::new(AddExpr::new(
Box::new(ConstantExpr::new(10)),
Box::new(ConstantExpr::new(1)),
)),
}
}
}
fn main() {
let container = Arc::new(Container::new());
let container1 = Arc::clone(&container);
/*
let thread1 = thread::spawn(move || {
println!("thread1: {}", container1.x);
println!("thread1: {}", container1.cached_expr.run());
});
*/
println!("main: {}", container.x);
println!("main: {}", container.cached_expr.run());
//thread1.join().unwrap();
}
错误:
error[E0277]: the trait bound `Expr + 'static: std::marker::Send` is not satisfied
--> src/main.rs:64:19
|
64 | let thread1 = thread::spawn(move || {
| ^^^^^^^^^^^^^ `Expr + 'static` cannot be sent between threads safely
|
= help: the trait `std::marker::Send` is not implemented for `Expr + 'static`
= note: required because of the requirements on the impl of `std::marker::Send` for `std::sync::Arc<Expr + 'static>`
= note: required because it appears within the type `Container`
= note: required because of the requirements on the impl of `std::marker::Send` for `std::sync::Arc<Container>`
= note: required because it appears within the type `[closure@src/main.rs:64:33: 67:6 container1:std::sync::Arc<Container>]`
= note: required by `std::thread::spawn`
error[E0277]: the trait bound `Expr + 'static: std::marker::Sync` is not satisfied
--> src/main.rs:64:19
|
64 | let thread1 = thread::spawn(move || {
| ^^^^^^^^^^^^^ `Expr + 'static` cannot be shared between threads safely
|
= help: the trait `std::marker::Sync` is not implemented for `Expr + 'static`
= note: required because of the requirements on the impl of `std::marker::Send` for `std::sync::Arc<Expr + 'static>`
= note: required because it appears within the type `Container`
= note: required because of the requirements on the impl of `std::marker::Send` for `std::sync::Arc<Container>`
= note: required because it appears within the type `[closure@src/main.rs:64:33: 67:6 container1:std::sync::Arc<Container>]`
= note: required by `std::thread::spawn`
推荐答案
我发现错误信息非常简单:
I find the error message pretty straightforward:
- 特征
std::marker::Send
没有为Expr + 'static
实现 - 需要,因为
std::sync::Arc
的 - 必需,因为它出现在
Container
类型中 - 需要,因为
std::sync::Arc
的 - 必需,因为它出现在类型
[closure@src/main.rs:64:33: 67:6 container1:std::sync::Arc]
std::thread::spawn
需要
std::marker::Send
的实现要求>std::marker::Send
的实现要求- the trait
std::marker::Send
is not implemented forExpr + 'static
- required because of the requirements on the impl of
std::marker::Send
forstd::sync::Arc<Expr + 'static>
- required because it appears within the type
Container
- required because of the requirements on the impl of
std::marker::Send
forstd::sync::Arc<Container>
- required because it appears within the type
[closure@src/main.rs:64:33: 67:6 container1:std::sync::Arc<Container>]
- required by
std::thread::spawn
您正在尝试将 Arc
移动到另一个线程,但它包含一个 Arc
,不能保证安全跨线程发送(Send
)或共享(Sync
).
You are trying to move your Arc<Container>
to another thread, but it contains an Arc<Expr + 'static>
, which cannot be guaranteed to be safely sent (Send
) or shared (Sync
) across threads.
将 Send
和 Sync
作为超特征添加到 Expr:
Either add Send
and Sync
as supertraits to Expr:
pub trait Expr: Send + Sync { /* ... */ }
或者将它们作为 trait bound 添加到你的 trait 对象中:
Or add them as trait bounds to your trait objects:
pub struct AddExpr {
expr1: Box<Expr + Send + Sync>,
expr2: Box<Expr + Send + Sync>,
}
impl AddExpr {
pub fn new(expr1: Box<Expr + Send + Sync>, expr2: Box<Expr + Send + Sync>) -> Self {
Self { expr1, expr2 }
}
}
struct Container {
x: i32,
cached_expr: Arc<Expr + Send + Sync>,
}
另见:
这篇关于跨线程共享具有特征对象作为属性的结构的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!