Bird
Raised Fist0
Rustprogramming~20 mins

Creating threads in Rust - Practice Exercises

Choose your learning style10 modes available
Challenge - 5 Problems
🎖️
Rust Thread Master
Get all challenges correct to earn this badge!
Test your skills under time pressure!
❓ Predict Output
intermediate
2:00remaining
What is the output of this Rust thread code?

Consider the following Rust program that creates a thread and prints a message. What will it print?

Rust
use std::thread;

fn main() {
    let handle = thread::spawn(|| {
        println!("Hello from the thread!");
    });
    handle.join().unwrap();
    println!("Hello from the main thread!");
}
AHello from the main thread!
BHello from the thread!\nHello from the main thread!
CHello from the thread!
DHello from the main thread!\nHello from the thread!
Attempts:
2 left
💡 Hint

Remember that join() waits for the thread to finish before continuing.

❓ Predict Output
intermediate
2:00remaining
What happens if you don't join a thread?

Look at this Rust program that spawns a thread but does not join it. What will be the output?

Rust
use std::thread;
use std::time::Duration;

fn main() {
    thread::spawn(|| {
        thread::sleep(Duration::from_millis(50));
        println!("Thread done");
    });
    println!("Main done");
}
AMain done
BThread done\nMain done
CMain done\nThread done
DThread done
Attempts:
2 left
💡 Hint

The main thread may finish before the spawned thread prints anything.

🔧 Debug
advanced
2:00remaining
Why does this Rust thread code fail to compile?

Examine this Rust code that tries to spawn a thread using a variable from the main thread. Why does it fail to compile?

Rust
use std::thread;

fn main() {
    let s = String::from("hello");
    let handle = thread::spawn(|| {
        println!("{}", s);
    });
    handle.join().unwrap();
}
AThe 'join' method is called incorrectly without handling the Result.
BThe variable 's' is not mutable, so it cannot be used inside the thread.
CThe thread::spawn function requires the closure to return a value, but this closure returns nothing.
DThe closure does not have the 'move' keyword, so it cannot capture 's' by value for the thread.
Attempts:
2 left
💡 Hint

Think about how variables are captured by closures when spawning threads.

📝 Syntax
advanced
2:00remaining
Which option correctly creates and joins multiple threads in Rust?

Choose the code snippet that correctly creates 3 threads, each printing its index, and waits for all to finish.

A
let mut handles = vec![];
for i in 0..3 {
    let handle = thread::spawn(|| {
        println!("Thread {}", i);
    });
    handles.push(handle);
}
for handle in handles {
    handle.join().unwrap();
}
B
let mut handles = vec![];
for i in 0..3 {
    let handle = thread::spawn(move || {
        println!("Thread {}", i);
    });
    handles.push(handle);
}
for handle in handles {
    handle.join();
}
C
let mut handles = vec![];
for i in 0..3 {
    let i = i;
    let handle = thread::spawn(move || {
        println!("Thread {}", i);
    });
    handles.push(handle);
}
for handle in handles {
    handle.join().unwrap();
}
D
let mut handles = vec![];
for i in 0..3 {
    let handle = thread::spawn(|| {
        println!("Thread {}", i);
    });
    handles.push(handle);
}
for handle in handles {
    handle.join();
}
Attempts:
2 left
💡 Hint

Remember to use move to capture the loop variable correctly and to unwrap the join result.

🚀 Application
expert
2:00remaining
What is the output of this Rust program using thread::scope?

This Rust program uses thread::scope to spawn threads that borrow a variable. What will it print?

Rust
use std::thread;

fn main() {
    let data = vec![1, 2, 3];
    thread::scope(|s| {
        for &num in &data {
            s.spawn(|| {
                println!("Number: {}", num);
            });
        }
    });
}
ANumber: 1\nNumber: 2\nNumber: 3
BNumber: 3\nNumber: 2\nNumber: 1
CCompilation error due to borrowing 'data' inside threads
DRuntime panic due to data being moved
Attempts:
2 left
💡 Hint

thread::scope allows threads to borrow variables safely.

Practice

(1/5)
1. What does thread::spawn do in Rust?
easy
A. It stops all threads immediately.
B. It pauses the current thread for a set time.
C. It creates a new thread to run code concurrently.
D. It merges two threads into one.

Solution

  1. Step 1: Understand the purpose of thread::spawn

    This function is used to start a new thread that runs code independently from the main thread.
  2. Step 2: Compare options with the function's role

    Only "It creates a new thread to run code concurrently." correctly describes creating a new thread. Other options describe unrelated actions.
  3. Final Answer:

    It creates a new thread to run code concurrently. -> Option C
  4. Quick Check:

    thread::spawn creates threads [OK]
Hint: Remember: spawn means start a new thread [OK]
Common Mistakes:
  • Confusing spawn with pausing or stopping threads
  • Thinking spawn merges threads
  • Assuming spawn waits for thread completion
2. Which of the following is the correct syntax to create a new thread in Rust?
easy
A. let handle = thread::spawn(|| { println!("Hello"); });
B. let handle = spawn::thread(|| { println!("Hello"); });
C. thread.spawn(|| println!("Hello"));
D. thread::create(|| { println!("Hello"); });

Solution

  1. Step 1: Recall the correct module and function

    The correct function to create a thread is thread::spawn from the std::thread module.
  2. Step 2: Check syntax correctness

    let handle = thread::spawn(|| { println!("Hello"); }); uses the correct syntax: thread::spawn(|| { ... }). Other options use wrong module names or functions.
  3. Final Answer:

    let handle = thread::spawn(|| { println!("Hello"); }); -> Option A
  4. Quick Check:

    Correct syntax uses thread::spawn [OK]
Hint: Use thread::spawn with a closure to start threads [OK]
Common Mistakes:
  • Swapping module and function names
  • Missing double colons (::) in path
  • Using non-existent functions like create()
3. What will be the output of this Rust code?
use std::thread;

fn main() {
    let handle = thread::spawn(|| {
        println!("Inside thread");
    });
    println!("Outside thread");
    handle.join().unwrap();
}
medium
A. Inside thread Outside thread
B. Outside thread Inside thread
C. Only Inside thread
D. Only Outside thread

Solution

  1. Step 1: Understand thread execution order

    The main thread prints "Outside thread" immediately. The spawned thread runs concurrently and prints "Inside thread".
  2. Step 2: Consider join() effect

    The join() waits for the spawned thread to finish, but does not change the order of prints already done.
  3. Final Answer:

    Outside thread Inside thread -> Option B
  4. Quick Check:

    Main prints first, spawned thread prints after [OK]
Hint: Main thread prints first, spawned thread runs concurrently [OK]
Common Mistakes:
  • Assuming spawned thread always prints first
  • Ignoring that join() waits but doesn't reorder prints
  • Thinking only one print appears
4. Identify the error in this Rust code that creates a thread:
use std::thread;

fn main() {
    let handle = thread::spawn(|| {
        println!("Hello from thread");
    });
    handle.join();
}
medium
A. println! macro cannot be used inside threads.
B. thread::spawn requires a named function, not a closure.
C. join() should be called before thread::spawn.
D. Missing call to unwrap() on join() result.

Solution

  1. Step 1: Check join() usage

    The join() method returns a Result that should be handled, usually by calling unwrap() to catch panics.
  2. Step 2: Verify other statements

    The other options are incorrect: println! macro works inside threads, thread::spawn accepts closures, and join() is called after spawn.
  3. Final Answer:

    Missing call to unwrap() on join() result. -> Option D
  4. Quick Check:

    Always unwrap join() result to handle errors [OK]
Hint: Always unwrap join() to handle thread errors [OK]
Common Mistakes:
  • Ignoring join()'s Result return
  • Thinking closures can't be used in spawn
  • Calling join() before spawn
5. You want to create 3 threads that each print their thread number (1, 2, 3). Which code correctly does this without data races?
use std::thread;

fn main() {
    for i in 1..=3 {
        thread::spawn(|| {
            println!("Thread number: {}", i);
        });
    }
}
hard
A. Move i into closure: thread::spawn(move || { println!("Thread number: {}", i); });
B. Use thread::spawn(|| { println!("Thread number: {}", i); }); as is.
C. Declare i as static before loop.
D. Use thread::spawn(|| println!("Thread number: {}", i)); without move.

Solution

  1. Step 1: Understand closure capturing in threads

    The variable i changes each loop iteration. Without move, the closure captures i by reference, causing data races.
  2. Step 2: Use move to capture i by value

    Adding move moves the current value of i into the closure, making each thread print its own number safely.
  3. Final Answer:

    Move i into closure: thread::spawn(move || { println!("Thread number: {}", i); }); -> Option A
  4. Quick Check:

    Use move closures to capture loop variables safely [OK]
Hint: Use move closures to capture loop variables in threads [OK]
Common Mistakes:
  • Not using move causes all threads to print last i value
  • Trying to declare i as static (not allowed here)
  • Assuming closure captures by value without move
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard