Skip to content
← All tracks

Fearless Concurrency: Threads, Channels, Shared State

Rust

Threads, scoped threads, channels, `Mutex`/`RwLock`, `Arc` and deadlock. Deliberately before async — async is a scheduling mechanism for concurrency, not a synonym for it.

This track is written for Rust, which isn't the mode you're browsing in.

0 / 22 solved · 2 articles
  1. 1. Not solved yet. Threads, spawn and join
  2. 2. Not solved yet. move closures: why the compiler forces your hand
  3. 3. Not solved yet. JoinHandle, panics and thread::Result
  4. 4. Not solved yet. Scoped threads: borrow, do not clone
  5. 5. Not solved yet. Balanced ranges: the arithmetic before the threads
  6. 6. Not solved yet. Send: what it actually guarantees
  7. 7. Not solved yet. Sync: T is Sync exactly when &T is Send
  8. 8. Not solved yet. unsafe impl Send, and the disjoint-capture trap
  9. 9. Not solved yet. Arc: shared ownership across threads
  10. 10. Not solved yet. Arc gives you sharing, not mutability
  11. 11. Not solved yet. Mutex and MutexGuard: you cannot forget to unlock
  12. 12. Not solved yet. Guard lifetimes: still holding the lock, still not meaning to
  13. 13. Not solved yet. Poisoning: what a panic does to a lock
  14. 14. Not solved yet. Index tagging: the pattern that makes concurrency testable
  15. 15. Not solved yet. Deadlock by lock ordering: the guarantee Rust does not give you
  16. 16. Not solved yet. mpsc channels: message passing basics
  17. 17. Not solved yet. The drop(tx) hang: a bug with no diagnostics
  18. 18. Not solved yet. sync_channel: bounded buffers and backpressure
  19. 19. Not solved yet. Condvar: a wakeup is a hint, the predicate is the truth
  20. 20. Not solved yet. Safe parallel mutation with chunks_mut
  21. 21. Not solved yet. Barrier: keeping workers in lock step
  22. 22. Not solved yet. park and unpark: building a blocking primitive by hand
  23. 23. Choosing your concurrency primitive Read
  24. 24. Structuring shared state so it cannot deadlock Read

Check yourself

4 questions · one attempt each

These do not count toward finishing the track. They are here to catch the things that are easy to read past.

0 / 4

Why must the original tx be dropped before rx.iter() finishes?

let (tx, rx) = mpsc::channel();
for i in 0..3 {
    let tx = tx.clone();
    thread::spawn(move || tx.send(i * 10).unwrap());
}
drop(tx);
rx.iter().collect::<Vec<_>>()
Question 1 of 4