Challenge - 5 Problems
Concurrency Safety Master
Get all challenges correct to earn this badge!
Test your skills under time pressure!
❓ Predict Output
intermediate2:00remaining
Output of shared mutable state with Mutex
What is the output of this Rust program that uses a Mutex to safely increment a shared counter across threads?
Rust
use std::sync::{Arc, Mutex};
use std::thread;
fn main() {
let counter = Arc::new(Mutex::new(0));
let mut handles = vec![];
for _ in 0..5 {
let counter = Arc::clone(&counter);
let handle = thread::spawn(move || {
let mut num = counter.lock().unwrap();
*num += 1;
});
handles.push(handle);
}
for handle in handles {
handle.join().unwrap();
}
println!("{}", *counter.lock().unwrap());
}Attempts:
2 left
💡 Hint
Think about how Mutex and Arc work together to allow safe shared mutable access.
✗ Incorrect
The Mutex ensures only one thread can mutate the counter at a time, and Arc allows multiple ownership. Each thread increments the counter once, so the final value is 5.
🧠 Conceptual
intermediate1:30remaining
Rust's Send and Sync traits purpose
Which statement best describes the purpose of Rust's Send and Sync traits in concurrency safety?
Attempts:
2 left
💡 Hint
Think about what it means to move or share data safely across threads.
✗ Incorrect
Send means a type can be transferred to another thread safely. Sync means a type can be referenced from multiple threads safely.
🔧 Debug
advanced2:00remaining
Identify the concurrency safety issue
What error will this Rust code produce when compiled or run?
Rust
use std::thread;
fn main() {
let mut data = vec![1, 2, 3];
let handle = thread::spawn(|| {
data.push(4);
});
handle.join().unwrap();
println!("{:?}", data);
}Attempts:
2 left
💡 Hint
Consider how Rust handles ownership and borrowing when spawning threads.
✗ Incorrect
The closure tries to access `data` which is owned by main thread, but it is not moved or shared safely. Rust prevents this with a compile-time error.
📝 Syntax
advanced1:30remaining
Correct syntax for atomic increment
Which option correctly increments an AtomicUsize safely in multiple threads?
Rust
use std::sync::atomic::{AtomicUsize, Ordering};
fn main() {
let counter = AtomicUsize::new(0);
// increment code here
println!("{}", counter.load(Ordering::SeqCst));
}Attempts:
2 left
💡 Hint
Atomic types have special methods for safe mutation.
✗ Incorrect
AtomicUsize does not support direct arithmetic operators. fetch_add is the correct method to increment atomically.
🚀 Application
expert2:30remaining
Number of items in a concurrent HashMap after insertions
Given this Rust code using the `dashmap` crate for concurrent hashmap, how many items will be in the map after all threads finish?
Rust
use dashmap::DashMap;
use std::sync::Arc;
use std::thread;
fn main() {
let map = Arc::new(DashMap::new());
let mut handles = vec![];
for i in 0..10 {
let map = Arc::clone(&map);
let handle = thread::spawn(move || {
for j in 0..5 {
map.insert(i * 5 + j, i);
}
});
handles.push(handle);
}
for handle in handles {
handle.join().unwrap();
}
println!("{}", map.len());
}Attempts:
2 left
💡 Hint
Each thread inserts 5 unique keys; there are 10 threads.
✗ Incorrect
Each of the 10 threads inserts 5 unique keys, so total keys inserted are 10 * 5 = 50. DashMap handles concurrency safely.