Threads
A thread runs code at the same time as the rest of your program. Rust checks at compile time that threads can't break each other's data.
thread::spawn
thread::spawn takes a closure with no arguments and runs it on a new thread. A closure is a small function with no name. || 2 + 3 takes nothing and gives back 5; a longer body goes in braces, like || { ... }. You will learn closures fully in a later section.
spawn returns a JoinHandle right away, not the closure's value, while the new thread keeps working.
use std::thread;let h = thread::spawn(|| 2 + 3);You can also skip the use line and write std::thread::spawn.
When main ends, the whole program ends, even if other threads are not done.
join
h.join() waits for the thread to finish. It returns a Result: Ok with the closure's value, or Err if the thread panicked.
let n = h.join().unwrap(); // 5To wait for many threads, keep their handles in a Vec. Vec::new() makes an empty Vec. for _ in 0..3 repeats 3 times; _ means we do not need the number. for h in hs takes each handle out of the Vec in turn.
let mut hs = Vec::new();for _ in 0..3 { hs.push(thread::spawn(|| 5));}let mut total = 0;for h in hs { total += h.join().unwrap();}println!("{total}"); // 15move closures
A spawned thread may live longer than the function that started it. So its closure can't borrow local variables. If it tries, you get error E0373. Add move so the closure owns what it uses:
let v = vec![1, 2, 3];let h = thread::spawn(move || v.len());println!("{}", h.join().unwrap());// v was moved, so main can't use it nowScoped threads
thread::scope makes threads that must finish before the scope ends. Because of that, they can borrow local data without move.
let v = vec![1, 2, 3];thread::scope(|s| { s.spawn(|| println!("{}", v.len()));});println!("{:?}", v); // v is still oursAll threads made with s.spawn are joined when thread::scope returns.
Remember
spawnstarts a thread,joinwaits for it and gives back its value.- E0373 means a spawned closure borrows a local; add
move. - After
move, a non-Copy value belongs to the thread. - Use
thread::scopewhen threads only need to borrow.