Thread

  • A thread has its own thread-local stack. The default size of a spawned thread is 2 MiB (Mebibyte 220) - subject to change.
  • A thread can be spawned by calling std::thread::spawn
    #![allow(unused)] fn main() { pub fn spawn<F, T>(f: F) -> JoinHandle<T> where F: FnOnce() -> T, F: Send + 'static, T: Send + 'static, }

Spawning a thread

use std::thread; fn main() { let handler = thread::spawn(|| println!("{:?}", thread::current().id())); // wait until the spawned thread finishes its job handler.join().unwrap(); }

Create a thread with Builder and configure stack size

  • the stack size of the main thread is not determined by Rust
  • can set stack size via RUST_MIN_STACK env variable but Builder::stack_size will override it
use std::thread; fn main() { let handler = thread::Builder::new() .stack_size(1024 /* bytes */) .name("worker 1".to_string()) .spawn(|| { let current = thread::current(); println!("Name = {:?}, Id = {:?}", current.name().unwrap(), current.id()); }) .unwrap(); handler.join().unwrap(); println!("Main Thread ID = {:?}", thread::current().id()); }

Spawning many threads

use std::thread; fn main() { const NUM_OF_THREADS: usize = 10; let mut handlers: Vec<thread::JoinHandle<()>> = Vec::with_capacity(NUM_OF_THREADS); for _ in 1..=10 { handlers.push(thread::spawn(|| println!("{:?}", thread::current().id()))); } handlers.into_iter().for_each(move |h| h.join().unwrap()); println!("Main Thread ID = {:?}", thread::current().id()); }

Scoped Thread Ref

  • non-scoped threads cannot borrow non-'static value
  • scoped threads can borrow non-'static value as the scope guarantees all threads will be joined at the end of the scope
use std::thread; fn main() { let v = vec![1, 2, 3]; // the following code throws compile time error cuase // the thread can't borrow v // closure may outlive the current function let handler = thread::spawn(|| println!("{:?}", v)); // to fix the error, we need to move v into the closure like below // let handler = thread::spawn(move || println!("{:?}", v)); handler.join().unwrap(); }

With scoped thread:

use std::thread; fn main() { let s = "Hello".to_owned(); let mut v = vec![1, 2, 3]; thread::scope(|scope| { scope.spawn(|| { println!("soped thread borrows s"); dbg!(&s); }); scope.spawn(|| { println!("soped thread mutably borrows v"); v.push(4); v.push(5); }); // all threads join at the end of the scope }); println!("{v:?}"); // => [1, 2, 3, 4, 5] }