【问题标题】:Share function reference between threads in Rust [duplicate]在 Rust 中的线程之间共享函数引用 [重复]
【发布时间】:2020-01-08 13:11:35
【问题描述】:

我想在线程之间共享一个函数引用,但 Rust 编译器说 `dyn for<'r> std::ops::Fn(&'r std::string::String) -> std::string::String` cannot be shared between threads safely。在线程之间共享“常规”值时,我非常了解SendSyncArc<T>,但在这种情况下,我无法理解问题所在。函数在程序运行时有一个静态地址,所以我在这里看不到问题。

我怎样才能做到这一点?

fn main() {
    // pass a function..
    do_sth_multithreaded(&append_a);
    do_sth_multithreaded(&identity);
}

fn append_a(string: &String) -> String {
    let mut string = String::from(string);
    string.push('a');
    string
}

fn identity(string: &String) -> String {
    String::from(string)
}

fn do_sth_multithreaded(transform_fn: &dyn Fn(&String) -> String) {
    for i in 0..4 {
        let string = format!("{}", i);
        thread::spawn(move || {
            println!("Thread {}: {}", i, transform_fn(&string))
        });
    }
}

【问题讨论】:

  • 我知道这篇文章。 stackoverflow.com/questions/59442080/… 但我仍然想学习和理解为什么它没有像我想象的那样工作。
  • 为什么要使用&dyn Fn而不是函数指针? do_sth_multithreaded 也应该使用闭包吗?
  • 这还不是要求,不是。也许它可能在未来。
  • 我不知道“真正的”函数指针。它适用于这个函数定义fn do_sth_multithreaded(transform_fn: fn(&String) -> String) - 谢谢!调用如下所示:do_sth_multithreaded(identity);

标签: rust


【解决方案1】:

函数在程序运行时有一个静态地址,因此我在这里看不到问题。

这对函数来说很好,但是你传递了一个&dyn Fn,这也可能是一个闭包或(在不稳定的 Rust 中)一个实现该特征的自定义对象。而且这个对象可能没有静态地址。所以你不能保证对象会比你产生的线程寿命更长。

但这甚至不是编译器所抱怨的(还没有!)。它实际上是在抱怨它不知道您是否被允许从另一个线程访问Fn。同样,与函数指针无关,但与闭包有关。

这是适用于您的示例的签名:

fn do_sth_multithreaded(transform_fn: &'static (dyn Fn(&String) -> String + Sync))

注意'static 生命周期界限和Sync 界限。

虽然静态生命周期适用于这种情况,但这可能意味着您永远无法发送闭包。为了使这项工作正常工作,您需要使用范围线程系统(例如,来自crossbeam 板条箱)以确保do_sth_multithreaded 在返回之前等待线程完成。然后你可以放宽静态生命周期限制。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-09
    • 1970-01-01
    • 1970-01-01
    • 2018-01-08
    • 1970-01-01
    • 2023-03-25
    相关资源
    最近更新 更多