在Rust中使用多个线程时如何在结构上使用方法?

时间:2019-04-26 08:15:11

标签: multithreading rust thread-safety

我正在尝试编写一个在Rust中使用多个线程的程序,但是我无法找到一种有效的方法。我有一个具有某些字段(MyStructUP)的结构,并且将它包装在另一个结构(MyStruct)中,该结构将旧的结构放在std::sync::Arcstd::sync::Mutex中。 MyStructUP结构具有一个字段,该字段采用MyStruct的向量,并且在MyStructUP上实现了一种方法,该方法在该向量中的每个MyStruct上进行调用。当我尝试在新线程上进行这些递归调用时,出现关于在线程之间安全共享数据的错误。

我了解代码的生命周期问题(我尝试使用包装结构的Arc解决它),并且我认为我已经使用Mutex防止了数据争用,但是代码仍然不起作用。

以下是该代码的精简版本:

use std::sync::{Arc, Mutex};
use std::thread;

pub struct MyStructUP<'a> {
    pub output: Vec<&'a MyStruct<'a>>,
    pub post_exec: &'a Fn(&Self) -> (),
}

impl<'a> MyStructUP<'a> {
    pub fn new(out: Vec<&'a MyStruct<'a>>) -> Self {
        MyStructUP {
            output: out,
            post_exec: &|n| {},
        }
    }
    pub fn do_something(&mut self) -> () {
        for val in self.output.iter_mut() {
            let local_self = val.inner.clone();
            thread::spawn(move || {
                local_self.lock().unwrap().do_something();
            });
        }
        (self.post_exec)(self)
    }
}

pub struct MyStruct<'a> {
    pub inner: Arc<Mutex<MyStructUP<'a>>>,
}

impl<'a> MyStruct<'a> {
    pub fn new(out: Vec<&'a MyStruct<'a>>) -> Self {
        MyStruct {
            inner: Arc::new(Mutex::new(MyStructUP::new(out))),
        }
    }
    pub fn do_something(&self) -> () {
        self.inner.lock().unwrap().do_something();
    }
}

当我添加Arc和Mutex来包装结构时,我希望代码能够编译,但是代码仍然无法正常工作,并且出现错误

error[E0277]: `(dyn for<'r> std::ops::Fn(&'r MyStructUP<'a>) + 'a)` cannot be shared between threads safely
  --> src/lib.rs:19:13
   |
19 |             thread::spawn(move || {
   |             ^^^^^^^^^^^^^ `(dyn for<'r> std::ops::Fn(&'r MyStructUP<'a>) + 'a)` cannot be shared between threads safely
   |
   = help: the trait `std::marker::Sync` is not implemented for `(dyn for<'r> std::ops::Fn(&'r MyStructUP<'a>) + 'a)`
   = note: required because of the requirements on the impl of `std::marker::Send` for `&'a (dyn for<'r> std::ops::Fn(&'r MyStructUP<'a>) + 'a)`
   = note: required because it appears within the type `MyStructUP<'a>`
   = note: required because of the requirements on the impl of `std::marker::Send` for `std::sync::Mutex<MyStructUP<'a>>`
   = note: required because of the requirements on the impl of `std::marker::Send` for `std::sync::Arc<std::sync::Mutex<MyStructUP<'a>>>`
   = note: required because it appears within the type `[closure@src/lib.rs:19:27: 21:14 local_self:std::sync::Arc<std::sync::Mutex<MyStructUP<'a>>>]`
   = note: required by `std::thread::spawn`

编辑:我试图删除建议的kstep之类的结构字段内的所有引用。并获得以下代码:

use std::sync::{Arc, Mutex};
use std::thread;

pub struct MyStructUP {
    pub output: Vec<MyStruct>,
    pub post_exec: Arc<Fn(&Self) -> ()>,
}

impl MyStructUP {
    pub fn new(out: Vec<MyStruct>) -> Self {
        MyStructUP {
            output: out,
            post_exec: Arc::new(|n| {}),
        }
    }
    pub fn do_something(&mut self) -> () {
        for val in self.output.iter_mut() {
            let local_self = val.inner.clone();
            thread::spawn(move || {
                local_self.lock().unwrap().do_something();
            });
        }
        (self.post_exec)(self)
    }
}

pub struct MyStruct {
    pub inner: Arc<Mutex<MyStructUP>>,
}

impl<'a> MyStruct {
    pub fn new(out: Vec<MyStruct>) -> Self {
        MyStruct {
            inner: Arc::new(Mutex::new(MyStructUP::new(out))),
        }
    }
    pub fn do_something(&self) -> () {
        self.inner.lock().unwrap().do_something();
    }
}

但是现在我遇到2个错误:

`(dyn for<'r> std::ops::Fn(&'r MyStructUP) + 'static)` cannot be sent between threads safely

`(dyn for<'r> std::ops::Fn(&'r MyStructUP) + 'static)` cannot be sent between threads safely

help: the trait `std::marker::Send` is not implemented for `(dyn for<'r> std::ops::Fn(&'r MyStructUP) + 'static)`
note: required because of the requirements on the impl of `std::marker::Send` for `std::sync::Arc<(dyn for<'r> std::ops::Fn(&'r MyStructUP) + 'static)>`
note: required because it appears within the type `MyStructUP`
note: required because of the requirements on the impl of `std::marker::Send` for `std::sync::Mutex<MyStructUP>`
note: required because of the requirements on the impl of `std::marker::Send` for `std::sync::Arc<std::sync::Mutex<MyStructUP>>`
note: required because it appears within the type `[closure@src\main.rs:19:27: 21:14 local_self:std::sync::Arc<std::sync::Mutex<MyStructUP>>]`
note: required by `std::thread::spawn`
`(dyn for<'r> std::ops::Fn(&'r MyStructUP) + 'static)` cannot be shared between threads safely

`(dyn for<'r> std::ops::Fn(&'r MyStructUP) + 'static)` cannot be shared between threads safely

help: the trait `std::marker::Sync` is not implemented for `(dyn for<'r> std::ops::Fn(&'r MyStructUP) + 'static)`
note: required because of the requirements on the impl of `std::marker::Send` for `std::sync::Arc<(dyn for<'r> std::ops::Fn(&'r MyStructUP) + 'static)>`
note: required because it appears within the type `MyStructUP`
note: required because of the requirements on the impl of `std::marker::Send` for `std::sync::Mutex<MyStructUP>`
note: required because of the requirements on the impl of `std::marker::Send` for `std::sync::Arc<std::sync::Mutex<MyStructUP>>`
note: required because it appears within the type `[closure@src\main.rs:19:27: 21:14 local_self:std::sync::Arc<std::sync::Mutex<MyStructUP>>]`
note: required by `std::thread::spawn`

0 个答案:

没有答案