具有不同功能的 Vector 的多线程

Multithreading with a Vector of different functions

我正在尝试 运行 在不同线程上执行多个函数。我写了这个有效的(最小)代码

use std::thread;

fn f1(count: usize) {
    for i in 0..count { /*do something*/ }
}

fn f2(count: usize) {
    for i in 0..count { /*do something*/ }
}

fn run(ops: &Vec<impl Fn(usize) + Sync + Send + Copy + 'static>) {
    for i in 0..ops.len() {
        let func = ops[i];
        thread::spawn(move || func(1000));
    }
}

fn main() {
    let ops = vec![f1, f1]; // putting the same function twice
    run(&ops);
}

但是,一旦我发送不同的函数

    let ops = vec![f1, f2];

编译失败。据我了解,我不能在同一个向量中保存不同的类型(我猜,函数有不同的内存要求,尽管我不太确定函数指针是如何工作的)。

我尝试在 SO 上浏览类似问题,并尝试了这个解决方案

    let ops: Vec<&dyn Fn(usize)> = vec![&f1, &f2];

我收到这个错误

`dyn Fn(usize)` cannot be shared between threads safely
the trait `Sync` is not implemented for `dyn Fn(usize)`

我在努力理解基本问题时陷入困境。你对我应该如何理解这个问题有什么见解,以及如何解决它的任何指示吗?

谢谢!

正如你可以用 impl 添加 Sync 标记一样,你也可以用 &dyn 添加它,但你可能需要括号来消除歧义:

fn run(ops: &Vec<&'static (dyn Fn(usize) + Sync)>)

两条小评论:

  • 一般来说,使用 &[…] 而不是 &Vec<…> 更灵活,更受青睐。
  • 不需要在 rust 中做 for i in 0…foos.len()for foo in foos 就可以了。 (您可能偶尔需要使用 for foo in &foosfor foo in foos.iter()。如果确实需要索引,.enumerate() 很方便。)
  • 如果 'static 很麻烦(例如因为你想传入一些捕获局部变量的闭包并且不能是 'static),你可以使用作用域线程(example),或将拥有的 Fns 作为 Vec<Box<dyn Fn(usize) + Sync>>.