简体   繁体   中英

chunks_exact_mut threading lifetimes

The following code produces interesting results:

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

Why does 'chunking' v change the lifetime? Without 'chunking' v , the code performs correctly. So why now does it throw an error?

The problem here is that thread::spawn completely decouples the lifetime from the rest, as the thread might continue to run while main is already finished.

x is a reference to a variable in main , and there is no guarantee that main lives longer than the thread.

I think what you really want here is a threading helper library like rayon , as they already solve those problems internally:

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]

Without "chunking" v , you're iterating over Vec<i32> . This iterator produces items of type i32 , so, no references, no lifetimes, the requirements for thread::spawn() (specifically the 'static requirement) are met.

chunks_exact_mut() , however, is defined on slices and gives iterator over &mut [T] , so it does have a reference. And since this reference refers v , which exists in main() , it is not 'static and does not work.

You can observe the same problem if you'll iterate over &v instead of v , since that iterator gives you &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

Other than that, I'd recommend using rayon as @Finomnis suggested.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM