我想通过线程与Arc<Mutex<Fn(i64)>>
共享一个结构。我已将以下问题最小化了:
use std::sync::{Arc, Mutex};
struct NonSendable {
problematic: Arc<Mutex<Fn(i64)>>,
}
fn main() {
let bad = NonSendable {
problematic: Arc::new(Mutex::new(|i| println!("{}", i))),
};
std::thread::spawn(|| {
for i in 0..10 {
let f = bad.problematic.lock().unwrap();
f(i);
}
});
}
但是,编译时会出错。
error[E0277]: `(dyn std::ops::Fn(i64) + 'static)` cannot be sent between threads safely
--> src/main.rs:13:5
|
13 | std::thread::spawn(|| {
| ^^^^^^^^^^^^^^^^^^ `(dyn std::ops::Fn(i64) + 'static)` cannot be sent between threads safely
|
= help: the trait `std::marker::Send` is not implemented for `(dyn std::ops::Fn(i64) + 'static)`
= note: required because of the requirements on the impl of `std::marker::Send` for `std::sync::Mutex<(dyn std::ops::Fn(i64) + 'static)
>`
= note: required because of the requirements on the impl of `std::marker::Sync` for `std::sync::Arc<std::sync::Mutex<(dyn std::ops::Fn(
i64) + 'static)>>`
= note: required because it appears within the type `NonSendable`
= note: required because of the requirements on the impl of `std::marker::Send` for `&NonSendable`
= note: required because it appears within the type `[closure@src/main.rs:13:24: 18:6 bad:&NonSendable]`
= note: required by `std::thread::spawn`
error: aborting due to previous error
我想我可能会明白为什么Fn
不是Send
或Sync
,但是Mutex
应该不能解决这个问题吗?我还尝试过Box
Fn
并改用FnMut
。
这里的最终目标是拥有Vec
的闭包,可以在一个线程中访问和修改闭包,而在另一个线程中进行读取,因此我认为我需要多个非mut
引用(或者也许Arc
)与Arc<Mutex<Vec<Fn>>>
或相似的成员共存于不同的线程中,但是如果无法使以上内容正常工作,则必须使用其他策略。
答案 0 :(得分:0)
在我问后不久就想出了这个问题(尽管我已经考虑了一天)。
Fn
只是一个特征,它本身不添加Send
。但是,闭包也是Send
,因此我需要将Mutex<Fn(i64)>
替换为Mutex<Fn(i64) + Send>
。这揭示了其他问题,但解决了原始问题。