Code does not work in parallel when using thread :: scoped

Can someone explain why the code below does not work in parallel? I think I do not understand how thread::scoped .

 use std::thread; use std::sync::{Arc, Mutex}; use std::time::Duration; use std::old_io::timer; fn main() { let buf = Arc::new(Mutex::new(Vec::<String>::new())); let res = test(buf); println!("{:?}", *res.lock().unwrap()); } fn test(buf: Arc<Mutex<Vec<String>>>) -> Arc<Mutex<Vec<String>>> { let guards: Vec<_> = (0..3).map( |i| { let mtx = buf.clone(); thread::scoped(|| { println!("Thread: {}", i); let mut res = mtx.lock().unwrap(); timer::sleep(Duration::seconds(5)); res.push(format!("thread {}", i)); }); }).collect(); buf } 

The code is based on examples here , where it is indicated:

The scoped function takes one argument, the closure indicated by double bars ||. This closure is performed in a new thread created in scope. The method is called a scope because it returns a “join protector” that automatically joins the child thread when it leaves the scope. Since we collect these guards in Vec, and this vector goes out of scope at the end of our program, our program will wait for each thread to complete before completion.

thanks

+6
source share
1 answer

This is a difficult case. The problem is a modest semicolon. Take a look at this collapsed code:

 thread::scoped(|| {}); 

This semicolon means that the result of collect not a JoinGuard vector - it a Vec<()> ! Each JoinGuard immediately discarded, causing the thread to end before the next iteration begins.

In resolving this problem, you will encounter the following problem, which is that i and mtx do not live long enough. You need to move them to insert:

 thread::scoped(move || {}) 
+10
source

Source: https://habr.com/ru/post/983507/


All Articles