Rust's headline promise is 'fearless concurrency' — and it's not marketing. The compiler statically prevents data races, so the entire class of 'works on my machine, corrupts data in production' threading bugs simply can't compile. This track shows how.
Spawning a thread
thread::spawn takes a closure and runs it on a new OS thread, returning a JoinHandle. The new thread runs concurrently with the one that spawned it. These are real OS threads (not green threads) — for lightweight async concurrency, that's the next track.
join: wait for completion
The spawning thread doesn't automatically wait for its children. Call .join() on the handle to block until that thread finishes and collect its result. Forget to join and main might exit while threads are still running — they'd be killed mid-work. join is how you say 'I need this thread's work before continuing.'
.join().unwrap() to surface any panic the thread hit.What the compiler watches
The moment a closure captures data and moves to another thread, the borrow checker's job gets harder: two threads might touch the same data at once. Rust's answer is the Send and Sync traits (last lesson of this track), which let the compiler prove, at compile time, that your sharing is race-free. Everything here rests on that guarantee.