Concurrency & async
15 steps in 5 sets of Rust.
Rust's claim about concurrency is stronger than its claim about memory: data races are a compile error, not a debugging session. Threads first, then shared state with Arc and Mutex, then channels.
The last set is async with tokio, which is a different model again and worth keeping separate in your head. Fifteen steps, and the compiler is doing more for you here than anywhere else in the language.
Threads
- Spawning threadsspawn starts a thread and hands back a handle; join waits and collects its value.
- move closuresA thread outlives the caller's stack frame, so it must own what it captures.
- Scoped threadsthread::scope lets threads borrow local data, because they cannot outlive the scope.
Channels
- Channelsmpsc moves values between threads: many senders, one receiver.
- A worker poolJobs down one channel, results back up another — a pool in twenty lines.
Async with tokio
- async and awaitAn async fn returns a future: nothing runs until a runtime polls it.
- Spawning taskstokio::spawn hands a future to the runtime and returns a JoinHandle.
- Running futures togetherjoin! waits for several futures at once; try_join! gives up on the first error.
- select! and timeoutsselect! takes whichever future finishes first — the shape of every timeout.
- Async channelstokio's mpsc is the async twin of the std channel: send and recv both await.
- Holding a lock across an awaittokio's Mutex may be held across an await point; the std one may not.
Encore
- parallel_sum.rsSplitting a big sum across threads, then comparing against the serial answer.