Skip to content

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:

LessonTopicRunnable
Threadsstd::thread, Arc<Mutex<T>>, joining handlesYes — browser Playground
Channelsstd::sync::mpsc, send/receive, ownership transferYes — browser Playground
Async Introasync/.await, futures, tokio runtimeCargo project only
Cargo & Testscargo new, #[test], cargo testCargo project only

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.

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 Send if it is safe to move to another thread.
  • A type is Sync if it is safe to share a reference across threads.
  • The compiler rejects code that violates these contracts — no sanitizers, no runtime checks needed.

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.");
}
What does it mean for a type to be Send in Rust?
Which standard library type is used to share mutable state safely between threads?
When should you prefer async/await over OS threads?