🎓 A1Learner
🔍

Rust Fearless Concurrency

Concurrency means a program makes progress on several jobs at once, instead of one job after another. Rust calls its approach fearless concurrency, because mistakes other languages find at run time are refused while the code is still being written.

spawn starts a second thread

A process is one running program. Threads are the independent parts inside it. They can run at the same time. Rust threads are 1:1 — one language thread is one operating-system thread:

let handle = thread::spawn(|| 40 + 2);
// a second thread now runs the closure; main carries on

join waits, and collects the answer

let answer = handle.join().unwrap();
println!("answer from thread = {}", answer); // answer from thread = 42

A race condition: the answer depends on the order

Threads reach shared data in an order nobody planned, and the answer depends on the order:

// two threads update one counter, with no plan for who goes first:
counter += 1; // thread A reads 5 and plans to write 6
counter += 1; // thread B also reads 5 and also writes 6
// two updates happened, yet the counter ends at 6: one update was lost

A deadlock: each thread waits for the other

// thread A holds the first lock and waits for the second;
// thread B holds the second lock and waits for the first.
// Neither can ever continue: that frozen circle is a deadlock.

Two tool families — Rust dictates neither

You will meet both in this section. Pick per problem:

// pass messages over a channel:
tx.send(value); // the value travels to the receiver
// or share state behind a lock:
let shared = Arc::new(Mutex::new(value));

Example

use std::thread;
fn main() {
    let handle = thread::spawn(|| 40 + 2);
    let answer = handle.join().unwrap();
    println!("answer from thread = {}", answer);
}

Key points

  • Concurrent: several jobs make progress by taking turns, even on one processor core
  • Parallel: several jobs truly run at the same moment, on different cores
  • Fearless: Rust checks thread code with the same ownership and type rules as all code.
  • So many concurrency bugs become compile errors.
  • They do not stay rare run-time crashes.
  • The safety rules in this section guard both.
  • Concurrency is famously easy to get wrong.

In this example, thread::spawn starts a second thread that adds 40 + 2. The closure gives back 42, and spawn hands main a handle. handle.join() waits for the thread to finish and returns its value inside Ok, so unwrap() takes the 42 out. The println! then prints answer from thread = 42. Two parts of the program ran as separate threads. The handover was checked by the compiler. That is the fearless idea in miniature.

Note

In Rust writing, the word concurrent often covers both concurrent and parallel work.

Try it Yourself

Edit the code, then press Run.

Running is simulated · Rust Playground

Exercise

What does fearless concurrency mean in practice?