liveBook · Manning

Multithreading

As explained in Rust Servers, Services, and Apps

Multithreading is a technique for executing multiple threads of control within a process, potentially in parallel or through interleaving.

Multithreading runs work on multiple operating-system threads. In a web service, it is one way to handle concurrent demand within a service; async I/O is another. Threads can make use of multiple CPU cores, while context switching can add to service latency. section 1.2.1 section 1.2.2

Consider two independent file reads, each simulated with a blocking sleep. Called synchronously, a four-second read followed by a two-second read takes six seconds. Spawn each read on its own thread instead, then join both threads before the program exits. While one thread waits, another can do work. section 10.1 section 10.2

use std::thread;
use std::thread::sleep;
use std::time::Duration;
 
fn main() {
    println!("Hello before reading file!");
    let handle1 = thread::spawn(|| {                #1
        let file1_contents = read_from_file1();
        println!("{:?}", file1_contents);
    });
    let handle2 = thread::spawn(|| {                #2
        let file2_contents = read_from_file2();
        println!("{:?}", file2_contents);
    });
    handle1.join().unwrap();                        #3
    handle2.join().unwrap();                        #4
}
 
// function that simulates reading from a file
fn read_from_file1() -> String {
    sleep(Duration::new(4, –));
    String::from("Hello, there from file 1")
}
 
// function that simulates reading from a file
fn read_from_file2() -> String {
    sleep(Duration::new(2, –));
    String::from("Hello, there from file 2")
}

Follow the two `thread::spawn` calls and their matching `join` calls. Each closure performs a separate simulated read; the joins wait for both threads to finish. section 10.2

Actix Web applies this model at the server level. By default, its HTTP server starts one OS-native worker thread per logical CPU, with a separate application instance on each worker. Async I/O supplies a second level of concurrency: a worker can do other tasks while waiting on I/O. Handlers that access shared application state need the framework’s safe state-access mechanism rather than assuming all requests run on one thread. section 3.1.2 section 3.3

Rust also supports shared-memory and message-passing concurrency, with type-level guarantees governing how values are shared. Multithreading is therefore a useful choice to recognize both in explicit `std::thread` code and in the worker model of a web server—not a replacement for async I/O in either setting. section 1.2.2 section 3.3

How Rust Servers, Services, and Apps covers it

How deep it goes
Works through spawning and joining threads for simulated file reads, then identifies Actix worker defaults; does not detail thread scheduling internals.
Examples
Compares sequential and spawned four-second and two-second file reads, and uses Actix worker threads as a server example.
What it assumes
Starts with a synchronous Rust `main` and blocking `sleep` before introducing native threads and async tasks.
What you can do after
Apply it via Rust `thread::spawn` and `join`, and evaluate/understand how Actix workers handle parallel server work.
How it connects
Connects multithreading to async I/O, blocking operations, shared application state, and message-passing concurrency.

Also explained in

Compare how 11 books explain multithreading →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Rust Servers, Services, and Apps. The section links point to the parts of the book it draws on.