Concurrency and async in Rust
Using a type system that rules out data races at compile time, you write threads, channels and tokio-based async services.
Level 401 · 15 lessons · 15 practice labs
Lessons
Threads
- thread::spawn and move closures
- Send and Sync: how the type system keeps you safe
- Arc, Mutex and RwLock
- Channels: mpsc and crossbeam
- Data parallelism with rayon
- Atomic types and memory ordering
- Short task: hash files in parallel
async and tokio
- async, await and Future
- The tokio runtime and tasks
- A TCP server with tokio
- select!, timeouts and cancellation
- A JSON API with axum
- Graceful shutdown and signals
- Short task: a rate-limited TCP relay
Capstone
- Capstone: a multi-client log collection service
Practice labs
- Finding a forgotten await: In an async function that writes no record yet reports no error, find the never-awaited future from the compiler warning and make the test see the record.
- Not holding a lock across an await: Fix a counter service that carries a std Mutex guard past an await point by narrowing the lock scope and show the concurrent test no longer stalls.
- Summing an array with threads: Split a number array into four parts and sum it with thread::spawn and move closures, matching the single-threaded result.
- Protecting a shared ledger: Protect a balance table written by several threads with Arc<Mutex<..>> so no balance is lost in the concurrent test.
- Solving a Send error by design: Redesign a cache that cannot be moved to a thread because it uses Rc, using Arc and RwLock, and pass the read-heavy test.
- Collecting worker results over a channel: Complete code where three workers send line counts to the main thread over an mpsc channel and verify the total.
- Speeding up checksums with rayon: Parallelise a sequential file checksum loop with par_iter and show the result is the same and the time shorter.
- An atomic request counter and memory ordering: Replace a mutex counter with AtomicU64, choose the right Ordering and prove data publication with a ready flag in a test.
- Running tasks concurrently with tokio: Turn three sequential requests to the lab targets into concurrent ones with tokio::join! and show the total time drops.
- Timeouts and cancellation with select!: Cut a request to a slow target after two seconds with select! and sleep, without the cancelled task leaking resources.
- Limiting concurrency with a semaphore: Limit an async tool that checks a hundred targets to at most ten open connections at a time with a Semaphore.
- Finding code that blocks the event loop: Find the synchronous file read that delays responses in an async server and fix it with spawn_blocking or tokio::fs.
- A health endpoint with axum: Add a /health endpoint returning version and uptime as JSON to an axum app and verify it with a test.
- Validating a request body in axum: Validate the JSON body of a registration endpoint with a size limit and field checks, answering bad requests with 400 and a reason.
- A server that shuts down cleanly on a signal: Write a tokio server that refuses new connections on SIGTERM, finishes in-flight requests and then exits.
About this course
Using a type system that rules out data races at compile time, you write threads, channels and tokio-based async services.
What you will learn
- Threads
- async and tokio
- Capstone
Prerequisites
You should have practised the topics of the same path up to level 301.
Lab environment
Lessons run in your own Kali Linux terminal in the browser, connected to a private lab network. Nothing to install.
Frequently asked questions
- Is this course right for my level?
- The course is at level 401; it assumes you know the topics of the lower-level courses.
- Is there anything to install?
- No. Every lesson runs in your own lab environment that opens in the browser.
- How do lessons work?
- Each lesson has 8 to 10 steps and a short quiz. Early steps show the command to type, later steps give less help; if two attempts fail, the solution opens.
- Can I try it for free?
- Yes. The first three lessons of every course are free.