rust 42 lines · 7 steps

Graceful thread shutdown with an atomic flag

A worker pool signals its threads to stop by flipping one shared atomic boolean, then joins them cleanly.

Explained by highlit
1use std::sync::atomic::{AtomicBool, Ordering};
2use std::sync::Arc;
3use std::thread;
4use std::time::Duration;
5 
6struct WorkerPool {
7 shutdown: Arc<AtomicBool>,
8 handles: Vec<thread::JoinHandle<()>>,
9}
10 
11impl WorkerPool {
12 fn new(workers: usize) -> Self {
13 let shutdown = Arc::new(AtomicBool::new(false));
14 let mut handles = Vec::with_capacity(workers);
15 
16 for id in 0..workers {
17 let flag = Arc::clone(&shutdown);
18 handles.push(thread::spawn(move || {
19 while !flag.load(Ordering::Acquire) {
20 process_next_task(id);
21 thread::sleep(Duration::from_millis(50));
22 }
23 eprintln!("worker {id} draining and exiting");
24 }));
25 }
26 
27 WorkerPool { shutdown, handles }
28 }
29 
30 fn shutdown(self) {
31 self.shutdown.store(true, Ordering::Release);
32 for handle in self.handles {
33 let _ = handle.join();
34 }
35 }
36}
37 
38impl Drop for WorkerPool {
39 fn drop(&mut self) {
40 self.shutdown.store(true, Ordering::Release);
41 }
42}
01 / 01
STEP 01

Walkthrough

Space play step click any line
Three takeaways
  1. 1A single shared AtomicBool is enough to coordinate cooperative shutdown across many threads without locks.
  2. 2Acquire/Release ordering pairs the writer's signal with each reader's check so the flag flip is reliably observed.
  3. 3Implementing Drop as a safety net ensures workers stop even when explicit shutdown is skipped.

Related explainers

Share this explainer

Here's the card — post it anywhere.

Graceful thread shutdown with an atomic flag — share card
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code