A thread is a sequence of CPU instructions intended to run in order within a process. Operating systems schedule threads to give each access to the CPU. A process can contain multiple threads, allowing different pieces of work to make progress without waiting for one long sequence to finish. section 10.2 section 10.5.3
Concurrency does not require multiple CPU cores. When a thread waits for memory or I/O, it can be blocked and scheduled again when its data is available. Parallelism is different: it uses multiple physical cores at the same time. Threads within one process share a memory address space, unlike separate processes. section 10.0 section 10.5
Spawn two workers
In Rust, `thread::spawn(move || { ... })` starts work in a new thread. A small timing program spawns two threads that each sleep for 300 ms, then calls `join().unwrap()` on both handles before measuring the elapsed time. The handles make the waiting explicit: spawning starts the work; joining waits for it to finish. section 10.2.3
Listing 10.3 Creating two subthreads to perform work on our behalf
1 use std::{thread, time};
2
3 fn main() {
4 let start = time::Instant::now();
5
6 let handler_1 = thread::spawn(move || {
7 let pause = time::Duration::from_millis(300);
8 thread::sleep(pause.clone());
9 });
10
11 let handler_2 = thread::spawn(move || {
12 let pause = time::Duration::from_millis(300);
13 thread::sleep(pause.clone());
14 });
15
16 handler_1.join().unwrap();
17 handler_2.join().unwrap();
18
19 let finish = time::Instant::now();
20
21 println!("{:?}", finish.duration_since(start));
22 }
Follow the two `thread::spawn` calls, then the two `join` calls, to see where concurrent work begins and where the main thread waits. section 10.2.3
A few threads need not be expensive: the two-worker timing comparison found little creation overhead. Large numbers are a different matter. Each thread needs memory; scheduling and switching consume CPU time, and switching invalidates caches. CPU-heavy work can slow sharply once runnable threads outnumber physical cores. Choose a thread count for the workload rather than assuming that more threads mean more speed. section 10.2.3 section 10.2.4
Shared memory also requires care. If two spawned closures try to write the same variable, their order is not predictable because the OS schedules them. Rust rejects the illustrated attempt to give both threads and `main` access to that mutable data. Smaller concurrency mechanisms, such as coroutines, differ in another way: the OS schedules threads, while a process manages switching among its own smaller tasks. section 1.6.1 section 10.5.1










