9

当我将工作委派给线程时,我经常有一段数据会比所有线程都活得更久,例如numbers在以下示例中:

use std::thread;

fn main() {
    let numbers = vec![1, 2, 3];

    let thread_a = thread::spawn(|| println!("{}", numbers.len()));
    let thread_b = thread::spawn(|| println!("{}", numbers.len()));

    thread_a.join().unwrap();
    thread_b.join().unwrap();
}

它没有在任何地方修改,并且由于joins,可以保证线程使用它完成。但是,Rust 的借用检查器无法判断:

error[E0373]: closure may outlive the current function, but it borrows `numbers`, which is owned by the current function
 --> src/main.rs:6:34
  |
6 |     let thread_a = thread::spawn(|| println!("{}", numbers.len()));
  |                                  ^^                ------- `numbers` is borrowed here
  |                                  |
  |                                  may outlive borrowed value `numbers`
  |
note: function requires argument type to outlive `'static`
 --> src/main.rs:6:20
  |
6 |     let thread_a = thread::spawn(|| println!("{}", numbers.len()));
  |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: to force the closure to take ownership of `numbers` (and any other referenced variables), use the `move` keyword
  |
6 |     let thread_a = thread::spawn(move || println!("{}", numbers.len()));
  |                                  ^^^^^^^

到目前为止我看到的解决方案都涉及克隆数据(或克隆Arc数据)。但是,是否有可能在没有任何克隆的情况下做到这一点?

4

1 回答 1

6

你可能有错误的想法:克隆 anArc只是增加一个引用计数器并复制一个指针;它不执行任何额外的分配。当然,创建Arc涉及分配,但是,您已经在分配以构造Vec,因此额外的固定大小分配不太可能受到伤害。

如果你真正需要的只是长度,你可以在线程闭包之外计算它并将它存储在一个变量中;ausize跨越线程边界没有问题。

问题是编译器无法从使用中推断join()给定线程绑定到有限的生命周期......它甚至没有尝试。

在 Rust 1.0 之前,有一个构造thread::scoped函数允许你传入非'static引用,但由于内存安全问题,它必须不稳定。请参阅如何将堆栈变量的引用传递给线程?为替代品。

于 2015-06-12T05:14:29.917 回答