Concurrency, Testing & Cargo
Fearless Concurrency — What This Module Covers
Section titled “Fearless Concurrency — What This Module Covers”One of Rust’s boldest claims is fearless concurrency: writing multi-threaded programs without the data races that plague C, C++, or even Java. The compiler enforces the same ownership rules at thread boundaries, turning an entire class of bugs into compile-time errors rather than hard-to-reproduce runtime failures.
This module explores four pillars of production Rust:
| Lesson | Topic | Runnable |
|---|---|---|
| Threads | std::thread, Arc<Mutex<T>>, joining handles | Yes — browser Playground |
| Channels | std::sync::mpsc, send/receive, ownership transfer | Yes — browser Playground |
| Async Intro | async/.await, futures, tokio runtime | Cargo project only |
| Cargo & Tests | cargo new, #[test], cargo test | Cargo project only |
The Two Concurrency Models
Section titled “The Two Concurrency Models”Rust standard library gives you OS threads via std::thread. Each thread is a real OS-level thread with its own stack. Shared state between threads is protected by Arc<Mutex<T>> — the compiler will not let you pass a non-Send type across a thread boundary.
For I/O-bound workloads — network servers, file operations, many concurrent lightweight tasks — the async/.await model is more efficient. It uses a single-threaded or multi-threaded event loop (usually tokio) to schedule thousands of tasks without the overhead of an OS thread per task.
Why Rust Concurrency Is Different
Section titled “Why Rust Concurrency Is Different”In most languages, data races are a runtime problem. You write the code, run it, and occasionally it crashes or returns wrong results under load. In Rust:
- A type is
Sendif it is safe to move to another thread. - A type is
Syncif it is safe to share a reference across threads. - The compiler rejects code that violates these contracts — no sanitizers, no runtime checks needed.
Quick Preview
Section titled “Quick Preview”Here is the smallest meaningful concurrent Rust program — spawn a thread, wait for it, continue in main.
use std::thread;
fn main() { let handle = thread::spawn(|| { println!("Hello from a spawned thread!"); }); handle.join().unwrap(); println!("Main thread done.");}Compiling…