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]
}