Rust Tutorial · Smart Pointers and Concurrency · Lesson 24 of 29
Rust Threads and Channels
Run work in parallel with threads and scoped threads, and communicate between them with channels.
Threads
std::thread::spawn runs a closure on a new thread; join waits for it. Scoped threads
(std::thread::scope) can borrow local data, because they're guaranteed to finish before the scope ends.
use std::thread;
fn main() {
let numbers: Vec<u64> = (1..=1_000_000).collect();
let (left, right) = numbers.split_at(numbers.len() / 2);
let (a, b) = thread::scope(|s| {
let h1 = s.spawn(|| left.iter().sum::<u64>());
let h2 = s.spawn(|| right.iter().sum::<u64>());
(h1.join().unwrap(), h2.join().unwrap())
});
println!("halves: {a} + {b} = {}", a + b);
}
Output
halves: 125000250000 + 375000250000 = 500000500000
Run this on your computer — see “Get Started” for setup.
Channels
A channel (std::sync::mpsc) sends values from producer threads to a consumer; ownership of each message moves
with it:
use std::sync::mpsc;
use std::thread;
fn main() {
let (tx, rx) = mpsc::channel();
let mut workers = Vec::new();
for id in 1..=3 {
let tx = tx.clone();
workers.push(thread::spawn(move || {
tx.send((id, format!("result from worker {id}"))).unwrap();
}));
}
drop(tx); // close our sender so the loop below ends
let mut results: Vec<(i32, String)> = rx.iter().collect();
results.sort();
for (_, r) in results { println!("{r}"); }
for w in workers { w.join().unwrap(); }
}
Output
result from worker 1 result from worker 2 result from worker 3
Run this on your computer — see “Get Started” for setup.
Test yourself
Why can scoped threads borrow local variables?
They copy all dataThey are guaranteed to finish before the scope endsThey run on the main threadBorrowing is unchecked in threads
Show answer
Answer: They are guaranteed to finish before the scope ends