Consider the following Rust program that creates a thread and prints a message. What will it print?
use std::thread;
fn main() {
let handle = thread::spawn(|| {
println!("Hello from the thread!");
});
handle.join().unwrap();
println!("Hello from the main thread!");
}Remember that join() waits for the thread to finish before continuing.
The spawned thread prints first, then join() waits for it to finish. After that, the main thread prints its message.
Choose the correct statement about Rust threads.
Think about Rust's ownership and safety guarantees.
Rust enforces safe concurrency by requiring explicit synchronization (like Mutex or channels) to share data between threads.
Examine the code below. What error will the Rust compiler report?
use std::thread;
fn main() {
let v = vec![1, 2, 3];
let handle = thread::spawn(|| {
println!("{:?}", v);
});
handle.join().unwrap();
}Think about how closures capture variables and thread lifetimes.
The closure borrows `v` but the thread may outlive `v`'s scope, so Rust prevents this with a lifetime error.
What will this Rust program print?
use std::thread;
fn main() {
let v = vec![10, 20, 30];
let handle = thread::spawn(move || {
println!("{:?}", v);
});
handle.join().unwrap();
}Consider what the move keyword does to variable capture.
The move keyword transfers ownership of v into the closure, so it can safely be used inside the thread.
Choose the synchronization primitive that permits multiple readers or one writer concurrently.
Think about read-write locks.
RwLock allows multiple readers or one writer at a time, enabling more concurrency than a Mutex.