我正在尝试编写一个在Rust中使用多个线程的程序,但是我无法找到一种有效的方法。我有一个具有某些字段(MyStructUP
)的结构,并且将它包装在另一个结构(MyStruct
)中,该结构将旧的结构放在std::sync::Arc
和std::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`