Adr*_*des 1 thread-safety lifetime rust
我有下面的代码。随着注释掉的部分,它的工作。当我取消注释这些部分时,它不再编译。
如何调整注释部分以使其工作,即,我想让线程同时访问表达式树。
当我尝试它时,编译器从关于线程安全性的错误开始。
我读过 Rust 的书,知道 C/C++,但还没有完全理解 Rust 类型系统和语义。
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();
}
Run Code Online (Sandbox Code Playgroud)
错误:
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();
}
Run Code Online (Sandbox Code Playgroud)
我发现错误消息非常简单:
std::marker::Send没有实现Expr + 'staticstd::marker::Sendfor的 impl 的要求而需要std::sync::Arc<Expr + 'static>Containerstd::marker::Sendfor的 impl 的要求而需要std::sync::Arc<Container>[closure@src/main.rs:64:33: 67:6 container1:std::sync::Arc<Container>]std::thread::spawn您正在尝试将您的Arc<Container>线程移动到另一个线程,但它包含一个Arc<Expr + 'static>,不能保证跨线程安全地发送 ( Send) 或共享 ( Sync)。
将Send和Sync作为超特征添加到 Expr:
pub trait Expr: Send + Sync { /* ... */ }
Run Code Online (Sandbox Code Playgroud)
或者将它们作为 trait bound 添加到你的 trait 对象中:
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>,
}
Run Code Online (Sandbox Code Playgroud)
也可以看看: