Knowledge Test Score Board
— · 0%
Work through the questions below — your score updates as you go.
Keep going · grade bands mapped to DCU's honours scale
Only your first attempt at each question counts toward this score. Reload the page to reset.
This section contains 20 interactive knowledge checks designed to test your understanding of the materials covered in Chapter 10. The questions cover OS threads, message passing via channels, shared state using Mutex and Arc, atomic operations, and the marker traits that guarantee thread safety.
Please remember that many of the quizzes have multiple correct answers , and you must select all applicable options to succeed. I have carefully balanced the lengths of the answers, so take your time to evaluate each option thoroughly.
Good luck!
Derek.
Concept Match
Match the Concurrency Fundamentals derekmolloy.ie Drag each definition into its matching concept slot, then click Submit. Tap × to return a placed card to the pool.
Definition Pool
Physical simultaneity where multiple computations execute at the exact same instant.
A structural property where multiple tasks make progress in overlapping time periods.
An isolated execution environment with private memory space and resources.
A lightweight unit of execution that lives inside and shares memory with a process.
Submit
Which of the following statements accurately describe the behaviour of thread::spawn() in Rust? derekmolloy.ie
It creates a new OS thread and blocks the main thread until the new thread starts running.
It automatically ensures that all spawned threads are joined before the main function returns.
It requires a closure that must satisfy the 'static lifetime bound if it does not use scoped threads.
It returns a JoinHandle, which can be used to wait for the thread's completion and retrieve its result. Submit Answer
Spawning and Joining Threads derekmolloy.ie Drag snippets from the pool into the blanks so the program produces the output shown, then click Submit.
1 use std::thread;
2
3 fn main() {
4 // Spawn a thread that returns a value
5 let handle = thread:: ····· (|| {
6 42
7 });
8
9 // Wait for the thread to finish and retrieve the result
10 let result = handle. ····· ().unwrap();
11 println!("Thread returned: {}", result);
12 }
Available Snippets
join
spawn
wait
run
await
create
Submit
Why is the 'move' keyword frequently required when spawning a new thread? derekmolloy.ie
To satisfy the thread-safety requirements of the operating system's kernel-level scheduler.
To force the closure to take ownership of captured variables, ensuring they live long enough.
To prevent the main thread from accessing any variables until the spawned thread finishes.
To tell the compiler to optimise the closure body for faster concurrent execution. Submit Answer
Concept Match
Match the Channel Components derekmolloy.ie Drag each definition into its matching concept slot, then click Submit. Tap × to return a placed card to the pool.
Definition Pool
The transmitting end of a channel; it can be cloned to allow multiple producer threads.
Stands for 'Multiple Producer, Single Consumer', the standard channel type in Rust.
The receiving end of a channel; it cannot be cloned, ensuring a single consumer.
A non-blocking receive method that returns an error immediately if no message is waiting.
Submit
Predict the output: Channel Communication derekmolloy.ie Read the code below, then choose the terminal output it produces and click Submit.
1 use std::sync::mpsc;
2 use std::thread;
3
4 fn main() {
5 let (tx, rx) = mpsc::channel();
6
7 thread::spawn(move || {
8 tx.send(10).unwrap();
9 tx.send(20).unwrap();
10 });
11
12 let val1 = rx.recv().unwrap();
13 let val2 = rx.recv().unwrap();
14 println!("{} {}", val1, val2);
15 }
Submit Answer
When does a loop using a Receiver as an iterator (e.g., for msg in rx { ... }) terminate? derekmolloy.ie
When all corresponding Sender handles have been dropped and the channel buffer is empty.
Exactly 60 seconds after the last message was successfully transmitted through the pipe.
As soon as the buffer is empty, regardless of whether senders are still active.
Only when the developer explicitly calls an rx.close() method from the consumer thread. Submit Answer
In the context of Assignment 2 and responsive GUIs, why is try_recv() preferred over recv() inside the update() loop? derekmolloy.ie
Because recv() requires a mutable reference to the context, which is not available in egui.
Because recv() is a blocking call that would freeze the GUI until a new message arrives.
Because try_recv() automatically handles the synchronisation of background hardware threads.
Because try_recv() is significantly faster at processing complex data structures like JSON. Submit Answer
Concept Match
Match the Synchronisation Primitives derekmolloy.ie Drag each definition into its matching concept slot, then click Submit. Tap × to return a placed card to the pool.
Definition Pool
Allows multiple concurrent readers or exactly one exclusive writer; ideal for read-heavy data.
Enforces mutual exclusion, allowing only one thread at a time to access the protected data.
An Atomic Reference Counted pointer that enables multiple threads to share ownership of data.
A smart pointer that provides data access and automatically releases the lock when dropped.
Submit
Drag snippets from the pool into the blanks so the program produces the output shown, then click Submit.
1 use std::sync::{Arc, Mutex};
2 use std::thread;
3
4 fn main() {
5 // Create a shared counter
6 let counter = Arc::new(Mutex::new(0));
7 let mut handles = vec![];
8
9 for _ in 0..10 {
10 // Clone the Arc to share ownership
11 let counter_clone = Arc:: ····· (&counter);
12 let handle = thread::spawn(move || {
13 // Acquire the lock
14 let mut num = counter_clone. ····· ().unwrap();
15 *num += 1;
16 });
17 handles.push(handle);
18 }
19 }
Available Snippets
acquire
new
lock
read
clone
copy
Submit
What is 'Mutex Poisoning' in Rust? derekmolloy.ie
A hardware failure where the CPU fails to correctly execute an atomic compare-and-swap instruction.
An optimisation where the compiler permanently locks a mutex to prevent any further modifications.
A state where a thread panics while holding a lock, indicating the protected data may be inconsistent.
A security vulnerability where an external process injects malicious code into a shared memory region. Submit Answer
Why is Arc<T> used instead of Rc<T> for sharing data between threads? derekmolloy.ie
Because Arc allows the data to be stored in the program's read-only binary section.
Because Rc is restricted to sharing only primitive types like integers and booleans.
Because Arc uses atomic operations to update the reference count, ensuring it is thread-safe.
Because Rc uses non-atomic counters which could lead to data races on the reference count itself. Submit Answer
Concept Match
Match the Advanced Sync Concepts derekmolloy.ie Drag each definition into its matching concept slot, then click Submit. Tap × to return a placed card to the pool.
Definition Pool
A situation where two threads are each waiting for a lock held by the other, stalling indefinitely.
Allows a thread to sleep efficiently until another thread signals that a condition has changed.
The strongest memory ordering, ensuring a consistent global order of atomic operations.
A thread-safe boolean that can be loaded and stored without the overhead of a mutex lock.
Submit
Using an Atomic Stop Flag derekmolloy.ie Drag snippets from the pool into the blanks so the program produces the output shown, then click Submit.
1 use std::sync::atomic::{AtomicBool, Ordering};
2
3 fn main() {
4 let stop_flag = AtomicBool::new(false);
5
6 // Set the flag atomically
7 stop_flag. ····· (true, Ordering::SeqCst);
8
9 // Read the flag atomically
10 if stop_flag. ····· (Ordering::SeqCst) {
11 println!("Stopping...");
12 }
13 }
Submit
In a read-heavy workload where 100 threads read a value and only 1 thread writes it, why is RwLock<T> superior to Mutex<T>? derekmolloy.ie
Because RwLock uses a more advanced hardware-level cache that is only available on multi-core ARM processors.
Because Mutex requires a separate memory allocation for every reader thread that attempts to acquire the lock.
Because RwLock allows all 100 readers to access the data simultaneously, whereas Mutex would serialise them.
Because RwLock provides a compile-time guarantee that the writer thread will always have highest priority. Submit Answer
Which of the following describes 'Priority Inversion'? derekmolloy.ie
An optimisation where the OS scheduler prioritises background threads to save battery life.
A scenario where the main thread is forced to wait for all spawned threads to finish before exiting.
A situation where a high-priority thread is blocked by a low-priority thread holding a shared resource.
A logic error where a thread's priority is accidentally set to a negative value by the developer. Submit Answer
Concept Match
Match the Marker Traits derekmolloy.ie Drag each definition into its matching concept slot, then click Submit. Tap × to return a placed card to the pool.
Definition Pool
A type that can safely have its ownership transferred between thread boundaries.
A trait with no methods, used purely to provide information to the compiler.
A type that can safely be shared via references (&T) across multiple threads.
Types like Mutex or Atomic that allow mutation even when accessed via an immutable reference.
Submit
Why does the Rust compiler refuse to move an Rc<T> into a spawned thread? derekmolloy.ie
Because Rc<T> is too large to fit in the new thread's stack space without causing an overflow.
Because moving Rc<T> could lead to two threads updating the same counter simultaneously, causing a data race.
Because the thread::spawn function is hard-coded to only accept String and integer types.
Because Rc<T> does not implement the Send trait due to its use of non-atomic reference counting. Submit Answer
Regarding the relationship between Send and Sync, which of the following is TRUE? derekmolloy.ie
Any type that implements Sync must also explicitly implement the Copy trait.
If a type is Send, it is guaranteed to be Sync, as ownership transfer is more restrictive.
A type T is Sync if and only if a reference to it (&T) is Send.
The Sync trait is required for any data being sent through an mpsc channel. Submit Answer
Which of the following types are NOT Send or Sync and require 'unsafe' code or a Mutex to be used in threads? Select all that apply. derekmolloy.ie
AtomicU32, as it provides hardware-level synchronisation for its internal value.
RefCell<T>, as its runtime borrow checks are not thread-safe.
Raw pointers like *mut u8, as they carry no ownership or safety information.
String, as it is a complex heap-allocated type that requires strict management. Submit Answer
Congratulations on completing the Chapter 10 Knowledge Test!
Review any questions you missed to ensure a solid grasp of Rust’s ‘fearless concurrency’ model before moving on to networking and advanced edge patterns.