Rust 跨线程将trait对象作为属性共享结构

Rust 跨线程将trait对象作为属性共享结构,rust,thread-safety,lifetime,Rust,Thread Safety,Lifetime,我有下面的代码。有了注释掉的部分,它就开始工作了。当我取消注释部分时,它不再编译 我如何调整注释部分以使其工作,也就是说,我想让线程同时访问表达式树 当我尝试它时,编译器会以关于线程安全性的错误开始 我读过Rust的书,了解C/C++,但还不完全了解Rust类型系统和语义 use std::thread; use std::sync::Arc; pub trait Expr { fn run(&self) -> i32; } pub struct ConstantExp

我有下面的代码。有了注释掉的部分,它就开始工作了。当我取消注释部分时,它不再编译

我如何调整注释部分以使其工作,也就是说,我想让线程同时访问表达式树

当我尝试它时,编译器会以关于线程安全性的错误开始

我读过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();
}
使用std::thread;
使用std::sync::Arc;
pub特征表达式{
fn运行(&self)->i32;
}
康斯坦特克斯酒店{
n:i32,
}
康斯坦特斯普雷姆酒店{
新发布(n:i32)->Self{
自{n}
}
}
ConstantExpr的impl Expr{
fn运行(&self)->i32{
赛尔夫
}
}
pub结构加法器{
expr1:Box,
expr2:Box,
}
impl加法器{
pub fn new(expr1:Box,expr2:Box)->Self{
自我{expr1,expr2}
}
}
加法器的impl Expr{
fn运行(&self)->i32{
self.expr1.run()+self.expr2.run()
}
}
结构容器{
x:i32,
缓存的_expr:Arc,
}
impl容器{
fn new()->Self{
自我{
x:0,,
缓存的_expr:Arc::new(AddExpr::new(
盒子::新的(康斯坦特斯普::新的(10)),
盒子::新的(康斯坦特斯普::新的(1)),
)),
}
}
}
fn main(){
让container=Arc::new(container::new());
让container1=Arc::clone(&container);
/*
让thread1=thread::spawn(移动| |){
println!(“thread1:{}”,container1.x);
println!(“thread1:{}”,container1.cached_expr.run());
});
*/
println!(“main:{}”,container.x);
println!((“main:{}”,container.cached_expr.run());
//线程1.连接().展开();
}
错误:

error[E0277]:特性绑定'Expr+'static:std::marker::Send'不满足
-->src/main.rs:64:19
|
64 | let thread1=线程::繁殖(移动| |{
|^^^^^^^^^^^^^^^`Expr+'static`无法在线程之间安全发送
|
=help:trait`std::marker::Send`未为`Expr+'静态实现`
=注:由于'std::marker::Send'的impl中对'std::sync::Arc src/main.rs:64:19的要求,因此需要输入'std::marker::Send'
|
64 | let thread1=线程::繁殖(移动| |{
|^^^^^^^^^^^^^^ ^`Expr+'static`无法在线程之间安全共享
|
=帮助:特性'std::marker::Sync'未为'Expr+'静态实现`

=注意:由于'std::marker::Send'的impl中对'std::sync::Arc'的要求,因此需要此选项我发现错误消息非常简单:

  • trait
    std::marker::Send
    没有为
    Expr+'static
  • 由于
    std::sync::Arc
    std::marker::Send
    的impl上的要求而需要,无法保证跨线程安全发送(
    Send
    )或共享(
    sync

    Send
    Sync
    作为超级特征添加到Expr:

    pub trait Expr: Send + Sync { /* ... */ }
    
    或者将它们作为特征边界添加到特征对象:

    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>,
    }
    
    pub-struct-AddExpr{
    expr1:Box,
    expr2:Box,
    }
    impl加法器{
    pub fn new(expr1:Box,expr2:Box)->Self{
    自我{expr1,expr2}
    }
    }
    结构容器{
    x:i32,
    缓存的_expr:Arc,
    }
    
    另见:


    我发现错误消息非常简单:

    • trait
      std::marker::Send
      没有为
      Expr+'static
    • 由于
      std::sync::Arc
      std::marker::Send
      的impl上的要求而需要,无法保证跨线程安全发送(
      Send
      )或共享(
      sync

      Send
      Sync
      作为超级特征添加到Expr:

      pub trait Expr: Send + Sync { /* ... */ }
      
      或者将它们作为特征边界添加到特征对象:

      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>,
      }
      
      pub-struct-AddExpr{
      expr1:Box,
      expr2:Box,
      }
      impl加法器{
      pub fn new(expr1:Box,expr2:Box)->Self{
      自我{expr1,expr2}
      }
      }
      结构容器{
      x:i32,
      缓存的_expr:Arc,
      }
      
      另见: