首页 > 解决方案 > 如何在rust中的多个线程上传递具有特征的数据结构?

问题描述

我正在尝试存储我的应用程序的状态,其中包括在开始时初始化并在多个线程之间传递状态的特征列表,但我收到错误。

use std::sync::{Arc, RwLock};
use std::thread;
use std::time::Duration;

trait TestTrait {
    fn test(&self);
}

struct MyTestStruct {}

impl TestTrait for MyTestStruct {
    fn test(&self) {
        println!("Test trait called");
    }
}

struct DataStore {
    t: Box<dyn TestTrait>,
}

fn main() {
    let s = Arc::new(RwLock::new(DataStore {
        t: Box::new(MyTestStruct {}),
    }));
    let s_clone = s.clone();
    thread::spawn(move || {
        for i in 1..10 {
            s_clone.read().unwrap().t.test();
            println!("hi number {} from the spawned thread!", i);
            thread::sleep(Duration::from_millis(1));
        }
    });

    for i in 1..5 {
        println!("hi number {} from the main thread!", i);
        thread::sleep(Duration::from_millis(1));
    }
}

当我运行它时,我收到以下错误:

error[E0277]: `(dyn TestTrait + 'static)` cannot be sent between threads safely
   --> src/main.rs:26:5
    |
26  |     thread::spawn(move || {
    |     ^^^^^^^^^^^^^ `(dyn TestTrait + 'static)` cannot be sent between threads safely
    |
    = help: the trait `std::marker::Send` is not implemented for `(dyn TestTrait + 'static)`
    = note: required because of the requirements on the impl of `std::marker::Send` for `std::ptr::Unique<(dyn TestTrait + 'static)>`
    = note: required because it appears within the type `std::boxed::Box<(dyn TestTrait + 'static)>`
    = note: required because it appears within the type `DataStore`
    = note: required because of the requirements on the impl of `std::marker::Send` for `std::sync::RwLock<DataStore>`
    = note: required because of the requirements on the impl of `std::marker::Send` for `std::sync::Arc<std::sync::RwLock<DataStore>>`
    = note: required because it appears within the type `[closure@src/main.rs:26:19: 32:6 s_clone:std::sync::Arc<std::sync::RwLock<DataStore>>]`

error[E0277]: `(dyn TestTrait + 'static)` cannot be shared between threads safely
   --> src/main.rs:26:5
    |
26  |     thread::spawn(move || {
    |     ^^^^^^^^^^^^^ `(dyn TestTrait + 'static)` cannot be shared between threads safely
    |
    = help: the trait `std::marker::Sync` is not implemented for `(dyn TestTrait + 'static)`
    = note: required because of the requirements on the impl of `std::marker::Sync` for `std::ptr::Unique<(dyn TestTrait + 'static)>`
    = note: required because it appears within the type `std::boxed::Box<(dyn TestTrait + 'static)>`
    = note: required because it appears within the type `DataStore`
    = note: required because of the requirements on the impl of `std::marker::Sync` for `std::sync::RwLock<DataStore>`
    = note: required because of the requirements on the impl of `std::marker::Send` for `std::sync::Arc<std::sync::RwLock<DataStore>>`
    = note: required because it appears within the type `[closure@src/main.rs:26:19: 32:6 s_clone:std::sync::Arc<std::sync::RwLock<DataStore>>]`

我该如何解决?

标签: rust

解决方案


thread::spawn需要一个实现Send. Arc<T>SendT同时实现Send和时才实现Sync

Send并且Sync自动特征。您可以将自动特征添加到dyn Trait类型以提供有关已擦除类型的更多信息:

struct DataStore {
    t: Box<dyn TestTrait + Send + Sync>,
}

如果你要dyn TestTrait + Send + Sync到处写,那么另一种选择是将Send和声明Sync为 的超特征TestTrait

trait TestTrait: Send + Sync {
    fn test(&self);
}

推荐阅读