A spawned thread can outlive the scope that created it. So when its closure uses data from that scope, Rust faces a question: will the data still be alive when the thread reads it? The move keyword answers it.
Why threads need move closures
If a thread closure borrowed a local variable, and the spawning function returned before the thread finished, the borrow would dangle — the classic use-after-free. Rust refuses to compile that. The fix is move: the closure takes ownership of what it captures, so the data lives as long as the thread does, independent of the original scope.
Ownership crosses the thread boundary
With move, captured values are transferred into the thread. The spawning thread can no longer use them — they belong to the new thread now. This is the same move semantics from the Ownership track, applied across a thread boundary, and it's exactly what makes the transfer safe: only one thread owns the data.
What about sharing, not moving?
Sometimes you don't want to give data to one thread — you want several threads to share it. You can't move one value into many closures. That's where Arc (from the Smart Pointers track) comes back: clone an Arc per thread, and each thread owns a shared handle to the same data. The next two lessons build on exactly that.