下面的代码产生了有趣的结果:
use std::thread;
fn main() {
let mut handles = Vec::new();
let mut v = vec![1, 2, 3, 4];
for x in v.chunks_exact_mut(2) {
let handle = thread::spawn(move || {
println!("Here's a vector: {:?}", x);
});
handles.push(handle);
}
for h in handles { h.join().unwrap(); }
}
error[E0597]: `v` does not live long enough
--> src/main.rs:7:14
|
7 | for x in v.chunks_exact_mut(2) {
| ^^^^^^^^^^^^^^^^^^^^^
| |
| borrowed value does not live long enough
| argument requires that `v` is borrowed for `'static`
...
16 | }
| - `v` dropped here while still borrowed
为什么"分块"v
会改变生存期?没有对v
进行"分块"处理,代码可以正确执行。为什么现在会抛出错误呢?
这里的问题是thread::spawn
完全与其他线程解耦,因为当main
已经完成时,线程可能会继续运行。
x
是对main
中的一个变量的引用,不能保证main
的生存时间比线程长。
我认为你真正想要的是一个像rayon
这样的线程助手库,因为它们已经在内部解决了这些问题:
use rayon::prelude::*;
fn main() {
let mut v = vec![1, 2, 3, 4];
v.par_chunks_exact_mut(2).for_each(|x: &mut [i32]| {
let thread_id = std::thread::current().id();
println!("{:?}: Here's a vector: {:?}", thread_id, x);
});
}
ThreadId(5): Here's a vector: [1, 2]
ThreadId(2): Here's a vector: [3, 4]
不带" chunking"v
,你在Vec<i32>
上迭代。该迭代器产生i32
类型的项,因此,没有引用,没有生命周期,满足thread::spawn()
的要求(特别是'static
的要求)。
然而,chunks_exact_mut()
是在片上定义的,并在&mut [T]
上提供迭代器,因此确实有引用。由于此引用引用的v
存在于main()
中,因此它不是'static
,因此不起作用。
如果迭代&v
而不是v
,可以观察到同样的问题,因为迭代器给出的是&i32
s (playground):
error[E0597]: `v` does not live long enough
--> src/main.rs:7:14
|
7 | for x in &v {
| ^^
| |
| borrowed value does not live long enough
| argument requires that `v` is borrowed for `'static`
...
16 | }
| - `v` dropped here while still borrowed
除此之外,我建议使用@Finomnis建议的rayon
。