Skip to content

02. Fearless Concurrency

Rust’s type system handles data races at compile time, making concurrent code safe and reliable.

1. Multi-Threading with std::thread

Threads in Rust are OS threads.

use std::thread;
use std::time::Duration;

fn main() {
    let handle = thread::spawn(|| {
        for i in 1..10 {
            println!("hi number {} from the spawned thread!", i);
            thread::sleep(Duration::from_millis(1));
        }
    });

    for i in 1..5 {
        println!("hi number {} from the main thread!", i);
        thread::sleep(Duration::from_millis(1));
    }

    handle.join().unwrap(); // Wait for thread to finish
}

2. Message Passing with Channels

Rust uses “Do not communicate by sharing memory; instead, share memory by communicating.”

use std::sync::mpsc; // Multiple Producer, Single Consumer
use std::thread;

fn main() {
    let (tx, rx) = mpsc::channel();

    thread::spawn(move || {
        let val = String::from("hi");
        tx.send(val).unwrap(); // Ownership moves into the send method
    });

    let received = rx.recv().unwrap();
    println!("Got: {}", received);
}

3. Shared-State Concurrency

For shared memory, we use Arc<T> (Atomic Reference Counter) and Mutex<T> (Mutual Exclusion).

use std::sync::{Arc, Mutex};
use std::thread;

fn main() {
    let counter = Arc::new(Mutex::new(0));
    let mut handles = vec![];

    for _ in 0..10 {
        let counter = Arc::clone(&counter);
        let handle = thread::spawn(move || {
            let mut num = counter.lock().unwrap();
            *num += 1;
        });
        handles.push(handle);
    }

    for handle in handles {
        handle.join().unwrap();
    }

    println!("Result: {}", *counter.lock().unwrap());
}

With these advanced tools, we’re ready for the final step: Web Development with Actix!