liveBook · Manning

Blocking

As explained in Rust Servers, Services, and Apps

A blocking operation is an operation that prevents its executing thread or task from continuing until an external activity completes.

A blocking operation stops the current thread while it waits for an external activity to finish, such as reading a large file or querying a database. In synchronous code, work after that operation cannot continue until the wait ends. section 10.1

Two simulated file reads

A Rust program calls two file-reading functions in sequence. Each uses `std::thread::sleep` to simulate a delay: four seconds for the first read and two for the second. Because `main` waits for each call to return, the delays add up to six seconds. The functions simulate file reads; they do not perform actual file I/O. 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")
}

The revised program starts each simulated read with `thread::spawn`, then uses `join` to wait for both threads. The sleeps still block their respective threads, but the reads can proceed concurrently. section 10.2

Async processing takes a different scheduling approach: when a task waits for I/O, a runtime such as Tokio can schedule another task and later resume the first. This differs from `std::thread::sleep`, which blocks its current thread even when called inside an `async fn`. Choose between synchronous execution, threads, and async processing according to the work being done and where it waits. section 10.1 section 10.2

How Rust Servers, Services, and Apps covers it

How deep it goes
Defines blocking through thread waits and works through simulated delays and threaded code; does not examine operating system I/O internals.
Examples
Uses sequential simulated file reads with four- and two-second sleeps, then runs them on separate operating system threads.
What it assumes
Assumes familiarity with Rust functions and `main`, while defining what a blocking operation does before comparing concurrency approaches.
What you can do after
Diagnose/debug with it by identifying waits that hold up a thread and comparing sequential execution with separate-thread execution.
How it connects
Connects blocking to synchronous processing, multithreading, async runtimes, file I/O, and database access.

Also explained in

Compare how 9 books explain blocking →

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.