与受保护的非发送线程共享结构

时间:2018-12-05 03:50:16

标签: rust

我想通过线程与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不是SendSync,但是Mutex应该不能解决这个问题吗?我还尝试过Box Fn并改用FnMut

这里的最终目标是拥有Vec的闭包,可以在一个线程中访问和修改闭包,而在另一个线程中进行读取,因此我认为我需要多个非mut引用(或者也许Arc)与Arc<Mutex<Vec<Fn>>>或相似的成员共存于不同的线程中,但是如果无法使以上内容正常工作,则必须使用其他策略。

1 个答案:

答案 0 :(得分:0)

在我问后不久就想出了这个问题(尽管我已经考虑了一天)。

Fn只是一个特征,它本身不添加Send。但是,闭包也是Send,因此我需要将Mutex<Fn(i64)>替换为Mutex<Fn(i64) + Send>。这揭示了其他问题,但解决了原始问题。