One common challenge in concurrency is managing shared state across multiple threads. Rust's ownership model, along with types like Mutex and Arc (atomic reference counting), makes this task safe and efficient.
In this challenge, you will implement a generic shared state system and use it to create thread-safe counters and other shared data structures.
Implement three functions that demonstrate different aspects of shared state concurrency:
create_shared_data: Creates shared state with any type Tincrement_counter: Demonstrates multiple threads modifying shared statemodify_shared_data: Generic function for thread-safe modificationsThe create_shared_data function should:
TMutex and ArcThe increment_counter function should:
Arc<Mutex<i32>>The modify_shared_data function should:
unwrap() to simplify the codemain function to see how the functions are usedArc::new(Mutex::new(initial)) to create thread-safe containersArc when passing it to a new thread. e.g. let cloned = Arc::clone(&shared_data)lock().unwrap() to access the data inside the MutexSend trait and have a lifetime that outlives the thread 'staticuse std::sync::{Arc, Mutex};use std::thread::{self, JoinHandle};pub fn create_shared_data<T: Send + 'static>(initial: T) -> Arc<Mutex<T>> { // 1. Initialize and return a new Arc<Mutex<T>> with the initial value Arc::new(Mutex::new(initial))}pub fn increment_counter( counter: Arc<Mutex<i32>>, threads: usize, increments: usize,) -> Vec<JoinHandle<()>> { // 2. Increment the counter by the given increments using the given number of threads let mut handles = Vec::new(); for _ in 0..threads{ let cloned = Arc::clone(&counter); let handle = thread::spawn(move||{ let mut num = cloned.lock().unwrap(); for _n in 0..increments{ *num += 1; } }); handles.push(handle); } handles}pub fn modify_shared_data<T: Send + 'static>( data: Arc<Mutex<T>>, modifier: fn(&mut T),) -> JoinHandle<()> { // 3. Use a new thread to modify the shared data let clone = Arc::clone(&data); let handle = thread::spawn(move||{ let mut data = clone.lock().unwrap(); modifier(&mut *data) }); handle}// Example usagepub fn main() { let counter = create_shared_data(0); let handles = increment_counter(Arc::clone(&counter), 5, 10); for handle in handles { handle.join().unwrap(); } println!("Counter value: {}", *counter.lock().unwrap()); let shared_string = create_shared_data(String::from("Hello")); let handle = modify_shared_data(shared_string.clone(), |s| s.push_str(" World")); handle.join().unwrap(); println!("Modified string: {}", *shared_string.lock().unwrap());}use std::sync::{Arc, Mutex};use std::thread::{self, JoinHandle, spawn};pub fn create_shared_data<T>(initial: T) -> Arc<Mutex<T>> { Arc::new(Mutex::new(initial))}pub fn increment_counter( counter: Arc<Mutex<i32>>, threads: usize, increments: usize,) -> Vec<JoinHandle<()>> { (1..=threads) .map(|_| { let counter_clone = Arc::clone(&counter); spawn(move || *counter_clone.lock().unwrap() += increments as i32) }) .collect() // 2. Increment the counter by the given increments using the given number of threads}pub fn modify_shared_data<T: Send + 'static>( data: Arc<Mutex<T>>, modifier: fn(&mut T),) -> JoinHandle<()> { spawn(move || { let mut data = data.lock().unwrap(); modifier(&mut data); })}// Example usagepub fn main() { let counter = create_shared_data(0); let handles = increment_counter(Arc::clone(&counter), 5, 10); for handle in handles { handle.join().unwrap(); } println!("Counter value: {}", *counter.lock().unwrap()); let shared_string = create_shared_data(String::from("Hello")); let handle = modify_shared_data(shared_string.clone(), |s| s.push_str(" World")); handle.join().unwrap(); println!("Modified string: {}", *shared_string.lock().unwrap());}use std::sync::{Arc, Mutex};use std::thread::{self, spawn, JoinHandle};pub fn create_shared_data<T>(initial: T) -> Arc<Mutex<T>> where T: Send + Sync{ // 1. Initialize and return a new Arc<Mutex<T>> with the initial value Arc::new(Mutex::new(initial))}pub fn increment_counter( counter: Arc<Mutex<i32>>, threads: usize, increments: usize,) -> Vec<JoinHandle<()>> { // 2. Increment the counter by the given increments using the given number of threads let mut handles = Vec::<JoinHandle<()>>::new(); for _ in 0..threads { let count = counter.clone(); let handle = spawn(move||{ let mut num = count.lock().unwrap(); *num += increments as i32; }); handles.push(handle); } handles}pub fn modify_shared_data<T: Send + 'static>( data: Arc<Mutex<T>>, modifier: fn(&mut T),) -> JoinHandle<()> { let handle = spawn(move||{ let data = data.clone(); modifier(&mut data.lock().unwrap()); }); handle // 3. Use a new thread to modify the shared data}// Example usagepub fn main() { let counter = create_shared_data(0); let handles = increment_counter(Arc::clone(&counter), 5, 10); for handle in handles { handle.join().unwrap(); } println!("Counter value: {}", *counter.lock().unwrap()); let shared_string = create_shared_data(String::from("Hello")); let handle = modify_shared_data(shared_string.clone(), |s| s.push_str(" World")); handle.join().unwrap(); println!("Modified string: {}", *shared_string.lock().unwrap());}use std::sync::{Arc, Mutex};use std::thread::{self, spawn, JoinHandle};pub fn create_shared_data<T>(initial: T) -> Arc<Mutex<T>> where T: Send + Sync{ // 1. Initialize and return a new Arc<Mutex<T>> with the initial value Arc::new(Mutex::new(initial))}pub fn increment_counter( counter: Arc<Mutex<i32>>, threads: usize, increments: usize,) -> Vec<JoinHandle<()>> { // 2. Increment the counter by the given increments using the given number of threads let mut handles = Vec::<JoinHandle<()>>::new(); for _ in 0..threads { let count = counter.clone(); let handle = spawn(move||{ let mut num = count.lock().unwrap(); *num += increments as i32; }); handles.push(handle); } handles}pub fn modify_shared_data<T: Send + 'static>( data: Arc<Mutex<T>>, modifier: fn(&mut T),) -> JoinHandle<()> { // 3. Use a new thread to modify the shared data let handle = spawn(move||{ let data = data.clone(); modifier(&mut data.lock().unwrap()); }); handle}// Example usagepub fn main() { let counter = create_shared_data(0); let handles = increment_counter(Arc::clone(&counter), 5, 10); for handle in handles { handle.join().unwrap(); } println!("Counter value: {}", *counter.lock().unwrap()); let shared_string = create_shared_data(String::from("Hello")); let handle = modify_shared_data(shared_string.clone(), |s| s.push_str(" World")); handle.join().unwrap(); println!("Modified string: {}", *shared_string.lock().unwrap());}use std::sync::{Arc, Mutex};use std::thread::{self, JoinHandle};pub fn create_shared_data<T>(initial: T) -> Arc<Mutex<T>> { // 1. Initialize and return a new Arc<Mutex<T>> with the initial value Arc::new(Mutex::new(initial))}pub fn increment_counter( counter: Arc<Mutex<i32>>, threads: usize, increments: usize,) -> Vec<JoinHandle<()>> { // 2. Increment the counter by the given increments using the given number of threads (0..threads) .into_iter() .map(|_| { let c = counter.clone(); thread::spawn(move || { let mut num = c.lock().unwrap(); *num += increments as i32; }) }) .collect::<Vec<JoinHandle<()>>>()}pub fn modify_shared_data<T: Send + 'static>( data: Arc<Mutex<T>>, modifier: fn(&mut T),) -> JoinHandle<()> { // 3. Use a new thread to modify the shared data thread::spawn(move || modifier(&mut *data.lock().unwrap()))}// Example usagepub fn main() { let counter = create_shared_data(0); let handles = increment_counter(Arc::clone(&counter), 5, 10); for handle in handles { handle.join().unwrap(); } println!("Counter value: {}", *counter.lock().unwrap()); let shared_string = create_shared_data(String::from("Hello")); let handle = modify_shared_data(shared_string.clone(), |s| s.push_str(" World")); handle.join().unwrap(); println!("Modified string: {}", *shared_string.lock().unwrap());}use std::sync::{Arc, Mutex};use std::thread::{self, JoinHandle};pub fn create_shared_data<T>(initial: T) -> Arc<Mutex<T>> { Arc::new(Mutex::new(initial))}pub fn increment_counter( counter: Arc<Mutex<i32>>, threads: usize, increments: usize,) -> Vec<JoinHandle<()>> { let mut handles = Vec::new(); for _ in 0..threads { let counter_clone = Arc::clone(&counter); let handle = thread::spawn(move || { let mut num = counter_clone.lock().unwrap(); *num += increments as i32; }); handles.push(handle); } handles}pub fn modify_shared_data<T: Send + 'static>( data: Arc<Mutex<T>>, modifier: fn(&mut T),) -> JoinHandle<()> { thread::spawn(move || { let mut shared_data = data.lock().unwrap(); modifier(&mut *shared_data); })}// Example usagepub fn main() { let counter = create_shared_data(0); let handles = increment_counter(Arc::clone(&counter), 5, 10); for handle in handles { handle.join().unwrap(); } println!("Counter value: {}", *counter.lock().unwrap()); let shared_string = create_shared_data(String::from("Hello")); let handle = modify_shared_data(shared_string.clone(), |s| s.push_str(" World")); handle.join().unwrap(); println!("Modified string: {}", *shared_string.lock().unwrap());}use std::sync::{Arc, Mutex};use std::thread::{self, JoinHandle};pub fn create_shared_data<T>(initial: T) -> Arc<Mutex<T>> { Arc::new(Mutex::new(initial))}pub fn increment_counter( counter: Arc<Mutex<i32>>, threads: usize, increments: usize,) -> Vec<JoinHandle<()>> { let mut vecs = vec![]; for _ in 0..threads { let l = Arc::clone(&counter); let handle = thread::spawn(move || { let mut l = l.lock().unwrap(); *l += increments as i32; }); vecs.push(handle); } vecs}pub fn modify_shared_data<T: Send + 'static>( data: Arc<Mutex<T>>, modifier: fn(&mut T),) -> JoinHandle<()> { let handle = thread::spawn(move || { let mut locked = data.lock().unwrap(); modifier(&mut *locked); }); handle}// Example usagepub fn main() { let counter = create_shared_data(0); let handles = increment_counter(Arc::clone(&counter), 5, 10); for handle in handles { handle.join().unwrap(); } println!("Counter value: {}", *counter.lock().unwrap()); let shared_string = create_shared_data(String::from("Hello")); let handle = modify_shared_data(shared_string.clone(), |s| s.push_str(" World")); handle.join().unwrap(); println!("Modified string: {}", *shared_string.lock().unwrap());}use std::sync::{Arc, Mutex};use std::thread::{self, JoinHandle};pub fn create_shared_data<T>(initial: T) -> Arc<Mutex<T>> { // 1. Initialize and return a new Arc<Mutex<T>> with the initial value let res =Arc::new(Mutex::new(initial)); res}pub fn increment_counter( counter: Arc<Mutex<i32>>, threads: usize, increments: usize,) -> Vec<JoinHandle<()>> { // 2. Increment the counter by the given increments using the given number of threads let mut vec=Vec::new(); for _ in 0..threads { let counter = Arc::clone(&counter); let th = thread::spawn(move || { let mut num = counter.lock().unwrap(); *num += increments as i32; }); vec.push(th); } vec}pub fn modify_shared_data<T: Send + 'static>( data: Arc<Mutex<T>>, modifier: fn(&mut T),) -> JoinHandle<()> { // 3. Use a new thread to modify the shared // let data = Arc::clone(&data); let handle = thread::spawn(move || { let mut data = data.lock().unwrap(); modifier(&mut *data); }); handle}// Example usagepub fn main() { let counter = create_shared_data(0); let handles = increment_counter(Arc::clone(&counter), 5, 10); for handle in handles { handle.join().unwrap(); } println!("Counter value: {}", *counter.lock().unwrap()); let shared_string = create_shared_data(String::from("Hello")); let handle = modify_shared_data(shared_string.clone(), |s| s.push_str(" World")); handle.join().unwrap(); println!("Modified string: {}", *shared_string.lock().unwrap());}use std::sync::{Arc, Mutex};use std::thread::{self, JoinHandle};pub fn create_shared_data<T>(initial: T) -> Arc<Mutex<T>> { // 1. Initialize and return a new Arc<Mutex<T>> with the initial value Arc::new(Mutex::new(initial))}pub fn increment_counter( counter: Arc<Mutex<i32>>, threads: usize, increments: usize,) -> Vec<JoinHandle<()>> { // 2. Increment the counter by the given increments using the given number of threads let mut handles = vec![]; for _ in 0..threads { let counter_clone = Arc::clone(&counter); let handle = thread::spawn(move || { for _ in 0..increments { let mut counter = counter_clone.lock().unwrap(); *counter += 1; } }); handles.push(handle); } handles}pub fn modify_shared_data<T: Send + 'static>( data: Arc<Mutex<T>>, modifier: fn(&mut T),) -> JoinHandle<()> { // 3. Use a new thread to modify the shared data thread::spawn(move || { let mut res = data.lock().unwrap(); modifier(&mut *res) })}// Example usagepub fn main() { let counter = create_shared_data(0); let handles = increment_counter(Arc::clone(&counter), 5, 10); for handle in handles { handle.join().unwrap(); } println!("Counter value: {}", *counter.lock().unwrap()); let shared_string = create_shared_data(String::from("Hello")); let handle = modify_shared_data(shared_string.clone(), |s| s.push_str(" World")); handle.join().unwrap(); println!("Modified string: {}", *shared_string.lock().unwrap());}use std::sync::{Arc, Mutex};use std::thread::{self, JoinHandle};pub fn create_shared_data<T>(initial: T) -> Arc<Mutex<T>> { // 1. Initialize and return a new Arc<Mutex<T>> with the initial value Arc::new(Mutex::new(initial))}pub fn increment_counter( counter: Arc<Mutex<i32>>, threads: usize, increments: usize,) -> Vec<JoinHandle<()>> { // 2. Increment the counter by the given increments using the given number of threads let mut handles = vec![]; for _ in 0..threads { let clone_c = Arc::clone(&counter); let handle = thread::spawn(move || { *clone_c.lock().unwrap() += increments as i32; }); handles.push(handle); } handles}pub fn modify_shared_data<T: Send + 'static>( data: Arc<Mutex<T>>, modifier: fn(&mut T),) -> JoinHandle<()> { // 3. Use a new thread to modify the shared data thread::spawn(move || { modifier(&mut *data.lock().unwrap()); })}// Example usagepub fn main() { let counter = create_shared_data(0); let handles = increment_counter(Arc::clone(&counter), 5, 10); for handle in handles { handle.join().unwrap(); } println!("Counter value: {}", *counter.lock().unwrap()); let shared_string = create_shared_data(String::from("Hello")); let handle = modify_shared_data(shared_string.clone(), |s| s.push_str(" World")); handle.join().unwrap(); println!("Modified string: {}", *shared_string.lock().unwrap());}use std::sync::{Arc, Mutex};use std::thread::{self, JoinHandle};pub fn create_shared_data<T>(initial: T) -> Arc<Mutex<T>> { // 1. Initialize and return a new Arc<Mutex<T>> with the initial value Arc::new(Mutex::new(initial))}pub fn increment_counter( counter: Arc<Mutex<i32>>, threads: usize, increments: usize,) -> Vec<JoinHandle<()>> { // 2. Increment the counter by the given increments using the given number of threads let mut handles = vec![]; for _ in 0..threads { let clone_c = Arc::clone(&counter); let handle = thread::spawn(move || { *clone_c.lock().unwrap() += increments as i32; }); handles.push(handle); } handles}pub fn modify_shared_data<T: Send + 'static>( data: Arc<Mutex<T>>, modifier: fn(&mut T),) -> JoinHandle<()> { // 3. Use a new thread to modify the shared data thread::spawn(move || { modifier(&mut *data.lock().unwrap()); })}// Example usagepub fn main() { let counter = create_shared_data(0); let handles = increment_counter(Arc::clone(&counter), 5, 10); for handle in handles { handle.join().unwrap(); } println!("Counter value: {}", *counter.lock().unwrap()); let shared_string = create_shared_data(String::from("Hello")); let handle = modify_shared_data(shared_string.clone(), |s| s.push_str(" World")); handle.join().unwrap(); println!("Modified string: {}", *shared_string.lock().unwrap());}use std::sync::{Arc, Mutex};use std::thread::{self, JoinHandle};pub fn create_shared_data<T>(initial: T) -> Arc<Mutex<T>> { Arc::new(Mutex::new(initial))}pub fn increment_counter( counter: Arc<Mutex<i32>>, threads: usize, increments: usize,) -> Vec<JoinHandle<()>> { let mut handles = vec![]; for _ in 0..threads { let counter_clone = Arc::clone(&counter); handles.push(thread::spawn(move || *counter_clone.lock().unwrap() += increments as i32 )); } handles}pub fn modify_shared_data<T: Send + 'static>( data: Arc<Mutex<T>>, modifier: fn(&mut T),) -> JoinHandle<()> { thread::spawn(move || modifier(&mut *data.lock().unwrap()))}// Example usagepub fn main() { let counter = create_shared_data(0); let handles = increment_counter(Arc::clone(&counter), 5, 10); for handle in handles { handle.join().unwrap(); } println!("Counter value: {}", *counter.lock().unwrap()); let shared_string = create_shared_data(String::from("Hello")); let handle = modify_shared_data(shared_string.clone(), |s| s.push_str(" World")); handle.join().unwrap(); println!("Modified string: {}", *shared_string.lock().unwrap());}use std::sync::{Arc, Mutex};use std::thread::{self, JoinHandle};pub fn create_shared_data<T>(initial: T) -> Arc<Mutex<T>> { Arc::new(Mutex::new(initial))}pub fn increment_counter( counter: Arc<Mutex<i32>>, threads: usize, increments: usize,) -> Vec<JoinHandle<()>> { let handles = (0..threads).into_iter().map(|i| { let binding = counter.clone(); thread::spawn(move || { let mut c = binding.lock().unwrap(); *c = *c + increments as i32; }) }).collect(); handles}pub fn modify_shared_data<T: Send + 'static>( data: Arc<Mutex<T>>, modifier: fn(&mut T),) -> JoinHandle<()> { thread::spawn(move || { let mut d = data.lock().unwrap(); modifier(&mut d); })}// Example usagepub fn main() { let counter = create_shared_data(0); let handles = increment_counter(Arc::clone(&counter), 5, 10); for handle in handles { handle.join().unwrap(); } println!("Counter value: {}", *counter.lock().unwrap()); let shared_string = create_shared_data(String::from("Hello")); let handle = modify_shared_data(shared_string.clone(), |s| s.push_str(" World")); handle.join().unwrap(); println!("Modified string: {}", *shared_string.lock().unwrap());}use std::sync::{Arc, Mutex};use std::thread::{self, JoinHandle};pub fn create_shared_data<T>(initial: T) -> Arc<Mutex<T>> { // 1. Initialize and return a new Arc<Mutex<T>> with the initial Arc::new(Mutex::new(initial))}pub fn increment_counter( counter: Arc<Mutex<i32>>, threads: usize, increments: usize,) -> Vec<JoinHandle<()>> { // 2. Increment the counter by the given increments using the given number of threads let mut res: Vec<JoinHandle<()>> = Vec::new(); for _ in 0..threads { let c = Arc::clone(&counter); res.push(thread::spawn(move || { *c.lock().unwrap() += increments as i32; })); } res}pub fn modify_shared_data<T: Send + 'static>( data: Arc<Mutex<T>>, modifier: fn(&mut T),) -> JoinHandle<()> { // 3. Use a new thread to modify the shared data let c_data = Arc::clone(&data); thread::spawn(move || { modifier(&mut *c_data.lock().unwrap()); })}// Example usagepub fn main() { let counter = create_shared_data(0); let handles = increment_counter(Arc::clone(&counter), 5, 10); for handle in handles { handle.join().unwrap(); } println!("Counter value: {}", *counter.lock().unwrap()); let shared_string = create_shared_data(String::from("Hello")); let handle = modify_shared_data(shared_string.clone(), |s| s.push_str(" World")); handle.join().unwrap(); println!("Modified string: {}", *shared_string.lock().unwrap());}use std::sync::{Arc, Mutex};use std::thread::{self, JoinHandle};pub fn create_shared_data<T>(initial: T) -> Arc<Mutex<T>> { // 1. Initialize and return a new Arc<Mutex<T>> with the initial value Arc::new(Mutex::new(initial))}pub fn increment_counter( counter: Arc<Mutex<i32>>, threads: usize, increments: usize,) -> Vec<JoinHandle<()>> { // 2. Increment the counter by the given increments using the given number of threads let mut res = vec![]; for i in 0..threads{ let cloned = Arc::clone(&counter); let th = thread::spawn(move || { *cloned.lock().unwrap() += increments as i32 }); res.push(th); } res}pub fn modify_shared_data<T: Send + 'static>( data: Arc<Mutex<T>>, modifier: fn(&mut T),) -> JoinHandle<()> { // 3. Use a new thread to modify the shared data let cloned = Arc::clone(&data); thread::spawn(move||{modifier(&mut *cloned.lock().unwrap())})}// Example usagepub fn main() { let counter = create_shared_data(0); let handles = increment_counter(Arc::clone(&counter), 5, 10); for handle in handles { handle.join().unwrap(); } println!("Counter value: {}", *counter.lock().unwrap()); let shared_string = create_shared_data(String::from("Hello")); let handle = modify_shared_data(shared_string.clone(), |s| s.push_str(" World")); handle.join().unwrap(); println!("Modified string: {}", *shared_string.lock().unwrap());}use std::sync::{Arc, Mutex};use std::thread::{self, JoinHandle};pub fn create_shared_data<T>(initial: T) -> Arc<Mutex<T>> { Arc::new(Mutex::new(initial))}pub fn increment_counter( counter: Arc<Mutex<i32>>, threads: usize, increments: usize,) -> Vec<JoinHandle<()>> { let mut handles: Vec<JoinHandle<()>> = Vec::new(); for _ in 0..threads { let counter_clone = Arc::clone(&counter); let handle = thread::spawn(move || { let mut cunter_lock = counter_clone.lock().unwrap(); *cunter_lock += increments as i32; }); handles.push(handle); } handles}pub fn modify_shared_data<T: Send + 'static>( data: Arc<Mutex<T>>, modifier: fn(&mut T),) -> JoinHandle<()> { let clone = Arc::clone(&data); thread::spawn(move || { let mut data_lock = clone.lock().unwrap(); modifier(&mut data_lock); })}// Example usagepub fn main() { let counter = create_shared_data(0); let handles = increment_counter(Arc::clone(&counter), 5, 10); for handle in handles { handle.join().unwrap(); } println!("Counter value: {}", *counter.lock().unwrap()); let shared_string = create_shared_data(String::from("Hello")); let handle = modify_shared_data(shared_string.clone(), |s| s.push_str(" World")); handle.join().unwrap(); println!("Modified string: {}", *shared_string.lock().unwrap());}use std::sync::{Arc, Mutex};use std::thread::{self, JoinHandle};pub fn create_shared_data<T>(initial: T) -> Arc<Mutex<T>> { // 1. Initialize and return a new Arc<Mutex<T>> with the initial value Arc::new(Mutex::new(initial))}pub fn increment_counter( counter: Arc<Mutex<i32>>, threads: usize, increments: usize,) -> Vec<JoinHandle<()>> { // 2. Increment the counter by the given increments using the given number of threads (0..threads).map(|_| { let counter_clone = counter.clone(); thread::spawn( move ||{ *(counter_clone.lock().unwrap()) +=increments as i32; } )}) .collect() }pub fn modify_shared_data<T: Send + 'static>( data: Arc<Mutex<T>>, modifier: fn(&mut T),) -> JoinHandle<()> { // 3. Use a new thread to modify the shared data let shared_data = data.clone(); thread::spawn( move || {modifier(&mut(shared_data.lock().unwrap()))} )}// Example usagepub fn main() { let counter = create_shared_data(0); let handles = increment_counter(Arc::clone(&counter), 5, 10); for handle in handles { handle.join().unwrap(); } println!("Counter value: {}", *counter.lock().unwrap()); let shared_string = create_shared_data(String::from("Hello")); let handle = modify_shared_data(shared_string.clone(), |s| s.push_str(" World")); handle.join().unwrap(); println!("Modified string: {}", *shared_string.lock().unwrap());}use std::sync::{Arc, Mutex};use std::thread::{self, JoinHandle};pub fn create_shared_data<T>(initial: T) -> Arc<Mutex<T>> { // 1. Initialize and return a new Arc<Mutex<T>> with the initial value Arc::new(Mutex::new(initial))}pub fn increment_counter( counter: Arc<Mutex<i32>>, threads: usize, increments: usize,) -> Vec<JoinHandle<()>> { // 2. Increment the counter by the given increments using the given number of threads let mut handles = Vec::with_capacity(threads); for _ in 0..threads { let counter = Arc::clone(&counter); handles.push(thread::spawn(move || { let mut counter = counter.lock().unwrap(); *counter += increments as i32; })); } handles}pub fn modify_shared_data<T: Send + 'static>( data: Arc<Mutex<T>>, modifier: fn(&mut T),) -> JoinHandle<()> { // 3. Use a new thread to modify the shared data let data = Arc::clone(&data); thread::spawn(move || { let mut data = data.lock().unwrap(); modifier(&mut data); })}// Example usagepub fn main() { let counter = create_shared_data(0); let handles = increment_counter(Arc::clone(&counter), 5, 10); for handle in handles { handle.join().unwrap(); } println!("Counter value: {}", *counter.lock().unwrap()); let shared_string = create_shared_data(String::from("Hello")); let handle = modify_shared_data(shared_string.clone(), |s| s.push_str(" World")); handle.join().unwrap(); println!("Modified string: {}", *shared_string.lock().unwrap());}use std::sync::{ Arc, Mutex };use std::thread::{ self, JoinHandle };pub fn create_shared_data<T>(initial: T) -> Arc<Mutex<T>> { // 1. Initialize and return a new Arc<Mutex<T>> with the initial value Arc::new(Mutex::new(initial))}pub fn increment_counter( counter: Arc<Mutex<i32>>, threads: usize, increments: usize) -> Vec<JoinHandle<()>> { // 2. Increment the counter by the given increments using the given number of threads let mut rs = Vec::new(); for _ in 0..threads { let counter = Arc::clone(&counter); rs.push( thread::spawn(move || { for _ in 0..increments { let mut num = counter.lock().unwrap(); *num += 1; } }) ); } rs}pub fn modify_shared_data<T: Send + 'static>( data: Arc<Mutex<T>>, modifier: fn(&mut T)) -> JoinHandle<()> { // 3. Use a new thread to modify the shared data let clone = Arc::clone(&data); thread::spawn(move || { // Lock the mutex to get mutable access if let Ok(mut guard) = data.lock() { modifier(&mut *guard); } })}// Example usagepub fn main() { let counter = create_shared_data(0); let handles = increment_counter(Arc::clone(&counter), 5, 10); for handle in handles { handle.join().unwrap(); } println!("Counter value: {}", *counter.lock().unwrap()); let shared_string = create_shared_data(String::from("Hello")); let handle = modify_shared_data(shared_string.clone(), |s| s.push_str(" World")); handle.join().unwrap(); println!("Modified string: {}", *shared_string.lock().unwrap());}use std::sync::{ Arc, Mutex };use std::thread::{ self, JoinHandle };pub fn create_shared_data<T>(initial: T) -> Arc<Mutex<T>> { // 1. Initialize and return a new Arc<Mutex<T>> with the initial value Arc::new(Mutex::new(initial))}pub fn increment_counter( counter: Arc<Mutex<i32>>, threads: usize, increments: usize) -> Vec<JoinHandle<()>> { // 2. Increment the counter by the given increments using the given number of threads let mut rs = Vec::new(); for _ in 0..threads { let counter = Arc::clone(&counter); rs.push( thread::spawn(move || { for _ in 0..increments { let mut num = counter.lock().unwrap(); *num += 1; } }) ); } rs}pub fn modify_shared_data<T: Send + 'static>( data: Arc<Mutex<T>>, modifier: fn(&mut T)) -> JoinHandle<()> { // 3. Use a new thread to modify the shared data let clone = Arc::clone(&data); thread::spawn(move || { // Lock the mutex to get mutable access if let Ok(mut guard) = data.lock() { modifier(&mut *guard); } })}// Example usagepub fn main() { let counter = create_shared_data(0); let handles = increment_counter(Arc::clone(&counter), 5, 10); for handle in handles { handle.join().unwrap(); } println!("Counter value: {}", *counter.lock().unwrap()); let shared_string = create_shared_data(String::from("Hello")); let handle = modify_shared_data(shared_string.clone(), |s| s.push_str(" World")); handle.join().unwrap(); println!("Modified string: {}", *shared_string.lock().unwrap());}use std::sync::{Arc, Mutex};use std::thread::{self, JoinHandle};pub fn create_shared_data<T>(initial: T) -> Arc<Mutex<T>> { // 1. Initialize and return a new Arc<Mutex<T>> with the initial value Arc::new(Mutex::new(initial))}pub fn increment_counter( counter: Arc<Mutex<i32>>, threads: usize, increments: usize,) -> Vec<JoinHandle<()>> { // 2. Increment the counter by the given increments using the given number of threads (0..threads) .map(|_| { let clone = Arc::clone(&counter); thread::spawn(move || { *clone.lock().unwrap() += increments as i32 }) }) .collect::<Vec<_>>()}pub fn modify_shared_data<T: Send + 'static>( data: Arc<Mutex<T>>, modifier: fn(&mut T),) -> JoinHandle<()> { // 3. Use a new thread to modify the shared data let clone = Arc::clone(&data); thread::spawn(move ||{ modifier(&mut clone.lock().unwrap()); })}// Example usagepub fn main() { let counter = create_shared_data(0); let handles = increment_counter(Arc::clone(&counter), 5, 10); for handle in handles { handle.join().unwrap(); } println!("Counter value: {}", *counter.lock().unwrap()); let shared_string = create_shared_data(String::from("Hello")); let handle = modify_shared_data(shared_string.clone(), |s| s.push_str(" World")); handle.join().unwrap(); println!("Modified string: {}", *shared_string.lock().unwrap());}use std::sync::{Arc, Mutex};use std::thread::{self, JoinHandle};pub fn create_shared_data<T>(initial: T) -> Arc<Mutex<T>> { // 1. Initialize and return a new Arc<Mutex<T>> with the initial value let data = Arc::new(Mutex::new(initial)); data}pub fn increment_counter( counter: Arc<Mutex<i32>>, threads: usize, increments: usize,) -> Vec<JoinHandle<()>> { // 2. Increment the counter by the given increments using the given number of threads let mut handles = vec![]; for _ in 0..threads { let data_clone = Arc::clone(&counter); let handle = thread::spawn(move || { let mut num = data_clone.lock().unwrap(); *num += increments as i32; }); handles.push(handle); } handles}pub fn modify_shared_data<T: Send + 'static>( data: Arc<Mutex<T>>, modifier: fn(&mut T),) -> JoinHandle<()> { // 3. Use a new thread to modify the shared data thread::spawn(move || { let mut locked_data = data.lock().unwrap(); modifier(&mut locked_data); }) }// Example usagepub fn main() { let counter = create_shared_data(0); let handles = increment_counter(Arc::clone(&counter), 5, 10); for handle in handles { handle.join().unwrap(); } println!("Counter value: {}", *counter.lock().unwrap()); let shared_string = create_shared_data(String::from("Hello")); let handle = modify_shared_data(shared_string.clone(), |s| s.push_str(" World")); handle.join().unwrap(); println!("Modified string: {}", *shared_string.lock().unwrap());}use std::sync::{Arc, Mutex};use std::thread::{self, JoinHandle};pub fn create_shared_data<T>(initial: T) -> Arc<Mutex<T>> { // 1. Initialize and return a new Arc<Mutex<T>> with the initial value Arc::new(Mutex::new(initial))}pub fn increment_counter( counter: Arc<Mutex<i32>>, threads: usize, increments: usize,) -> Vec<JoinHandle<()>> { // 2. Increment the counter by the given increments using the given number of threads (0..threads) .map(|_| { let cloned = Arc::clone(&counter); thread::spawn(move || { *cloned.lock().unwrap() += increments as i32; }) }) .collect::<Vec<_>>()}pub fn modify_shared_data<T: Send + 'static>( data: Arc<Mutex<T>>, modifier: fn(&mut T),) -> JoinHandle<()> { // 3. Use a new thread to modify the shared data let cloned = Arc::clone(&data); thread::spawn(move || { modifier(&mut cloned.lock().unwrap()); })}// Example usagepub fn main() { let counter = create_shared_data(0); let handles = increment_counter(Arc::clone(&counter), 5, 10); for handle in handles { handle.join().unwrap(); } println!("Counter value: {}", *counter.lock().unwrap()); let shared_string = create_shared_data(String::from("Hello")); let handle = modify_shared_data(shared_string.clone(), |s| s.push_str(" World")); handle.join().unwrap(); println!("Modified string: {}", *shared_string.lock().unwrap());}use std::sync::{Arc, Mutex};use std::thread::{self, JoinHandle};pub fn create_shared_data<T>(initial: T) -> Arc<Mutex<T>> { // 1. Initialize and return a new Arc<Mutex<T>> with the initial value Arc::new(Mutex::new(initial))}pub fn increment_counter( counter: Arc<Mutex<i32>>, threads: usize, increments: usize,) -> Vec<JoinHandle<()>> { // 2. Increment the counter by the given increments using the given number of threads (0..threads).map(|_| { let share_counter = counter.clone(); thread::spawn(move|| { let mut guard = share_counter.lock().unwrap(); *guard += increments as i32 }) }).collect()}pub fn modify_shared_data<T: Send + 'static>( data: Arc<Mutex<T>>, modifier: fn(&mut T),) -> JoinHandle<()> { // 3. Use a new thread to modify the shared data let data = data.clone(); thread::spawn(move || { let mut guard = data.lock().unwrap(); modifier(&mut guard); })}// Example usagepub fn main() { let counter = create_shared_data(0); let handles = increment_counter(Arc::clone(&counter), 5, 10); for handle in handles { handle.join().unwrap(); } println!("Counter value: {}", *counter.lock().unwrap()); let shared_string = create_shared_data(String::from("Hello")); let handle = modify_shared_data(shared_string.clone(), |s| s.push_str(" World")); handle.join().unwrap(); println!("Modified string: {}", *shared_string.lock().unwrap());}use std::sync::{Arc, Mutex};use std::thread::{self, JoinHandle};pub fn create_shared_data<T>(initial: T) -> Arc<Mutex<T>> { // 1. Initialize and return a new Arc<Mutex<T>> with the initial value Arc::new(Mutex::new(initial))}pub fn increment_counter( counter: Arc<Mutex<i32>>, threads: usize, increments: usize,) -> Vec<JoinHandle<()>> { // 2. Increment the counter by the given increments using the given number of threads (0..threads).map(|_| { let counters = Arc::clone(&counter); thread::spawn(move || { // necessary lock() as guard and unwrap to access interior Arc prevent poisioning let mut data_guard = counters.lock().unwrap(); *data_guard += increments as i32; }) }).collect()}pub fn modify_shared_data<T: Send + 'static>( data: Arc<Mutex<T>>, modifier: fn(&mut T),) -> JoinHandle<()> { // 3. Use a new thread to modify the shared data let clone_data = Arc::clone(&data); thread::spawn(move || { modifier(&mut clone_data.lock().unwrap()) })}// Example usagepub fn main() { let counter = create_shared_data(0); let handles = increment_counter(Arc::clone(&counter), 5, 10); for handle in handles { handle.join().unwrap(); } println!("Counter value: {}", *counter.lock().unwrap()); let shared_string = create_shared_data(String::from("Hello")); let handle = modify_shared_data(shared_string.clone(), |s| s.push_str(" World")); handle.join().unwrap(); println!("Modified string: {}", *shared_string.lock().unwrap());}use std::sync::{Arc, Mutex};use std::thread::{self, JoinHandle};use std::ops::DerefMut;pub fn create_shared_data<T>(initial: T) -> Arc<Mutex<T>> { Arc::new((Mutex::new(initial)))}pub fn increment_counter( counter: Arc<Mutex<i32>>, threads: usize, increments: usize,) -> Vec<JoinHandle<()>> { // 2. Increment the counter by the given increments using the given number of threads let mut handles = vec![]; for _ in 0..threads{ let c = Arc::clone(&counter); let h = thread::spawn( move || { for _ in 0..increments{ *c.lock().unwrap().deref_mut() += 1; } }); handles.push(h); } handles}pub fn modify_shared_data<T: Send + 'static>( data: Arc<Mutex<T>>, modifier: fn(&mut T),) -> JoinHandle<()> { // 3. Use a new thread to modify the shared data thread::spawn( move||{ modifier( data.lock().unwrap().deref_mut()); })}// Example usagepub fn main() { let counter = create_shared_data(0); let handles = increment_counter(Arc::clone(&counter), 5, 10); for handle in handles { handle.join().unwrap(); } println!("Counter value: {}", *counter.lock().unwrap()); let shared_string = create_shared_data(String::from("Hello")); let handle = modify_shared_data(shared_string.clone(), |s| s.push_str(" World")); handle.join().unwrap(); println!("Modified string: {}", *shared_string.lock().unwrap());}use std::sync::{Arc, Mutex};use std::thread::{self, JoinHandle};pub fn create_shared_data<T>(initial: T) -> Arc<Mutex<T>> { Arc::new(Mutex::new(initial))}pub fn increment_counter( counter: Arc<Mutex<i32>>, threads: usize, increments: usize,) -> Vec<JoinHandle<()>> { // 2. Increment the counter by the given increments using the given number of threads (0..threads).map(|_| { let arc_count = Arc::clone(&counter); thread::spawn(move||{ let mut c = arc_count.lock().unwrap(); *c += increments as i32; }) }).collect()}pub fn modify_shared_data<T: Send + 'static>( data: Arc<Mutex<T>>, modifier: fn(&mut T),) -> JoinHandle<()> { let arc_data = Arc::clone(&data); thread::spawn(move ||{ let mut data = arc_data.lock().unwrap(); modifier(&mut data) })}// Example usagepub fn main() { let counter = create_shared_data(0); let handles = increment_counter(Arc::clone(&counter), 5, 10); for handle in handles { handle.join().unwrap(); } println!("Counter value: {}", *counter.lock().unwrap()); let shared_string = create_shared_data(String::from("Hello")); let handle = modify_shared_data(shared_string.clone(), |s| s.push_str(" World")); handle.join().unwrap(); println!("Modified string: {}", *shared_string.lock().unwrap());}use std::sync::{Arc, Mutex};use std::thread::{self, JoinHandle};pub fn create_shared_data<T>(initial: T) -> Arc<Mutex<T>> { // 1. Initialize and return a new Arc<Mutex<T>> with the initial value Arc::new(Mutex::new(initial))}pub fn increment_counter( counter: Arc<Mutex<i32>>, threads: usize, increments: usize,) -> Vec<JoinHandle<()>> { // 2. Increment the counter by the given increments using the given number of threads (0..threads) .map(|_| { let counter = Arc::clone(&counter); thread::spawn(move || { let mut counter = counter.lock().unwrap(); *counter += i32::try_from(increments).unwrap(); }) }) .collect()}pub fn modify_shared_data<T: Send + 'static>( data: Arc<Mutex<T>>, modifier: fn(&mut T),) -> JoinHandle<()> { // 3. Use a new thread to modify the shared data let data = Arc::clone(&data); thread::spawn(move || { modifier(&mut data.lock().unwrap()); })}// Example usagepub fn main() { let counter = create_shared_data(0); let handles = increment_counter(Arc::clone(&counter), 5, 10); for handle in handles { handle.join().unwrap(); } println!("Counter value: {}", *counter.lock().unwrap()); let shared_string = create_shared_data(String::from("Hello")); let handle = modify_shared_data(shared_string.clone(), |s| s.push_str(" World")); handle.join().unwrap(); println!("Modified string: {}", *shared_string.lock().unwrap());}use std::sync::{Arc, Mutex};use std::thread::{self, JoinHandle};pub fn create_shared_data<T>(initial: T) -> Arc<Mutex<T>> { // 1. Initialize and return a new Arc<Mutex<T>> with the initial value Arc::new(Mutex::new(initial))}pub fn increment_counter( counter: Arc<Mutex<i32>>, threads: usize, increments: usize,) -> Vec<JoinHandle<()>> { // 2. Increment the counter by the given increments using the given number of threads let mut handles = Vec::new(); for i in 0..threads { let counter = counter.clone(); handles.push(thread::spawn(move || { for i in 0..increments { *counter.lock().unwrap() += 1; } })); } handles}pub fn modify_shared_data<T: Send + 'static>( data: Arc<Mutex<T>>, modifier: fn(&mut T),) -> JoinHandle<()> { // 3. Use a new thread to modify the shared data thread::spawn(move || { modifier(&mut data.lock().unwrap()) })}// Example usagepub fn main() { let counter = create_shared_data(0); let handles = increment_counter(Arc::clone(&counter), 5, 10); for handle in handles { handle.join().unwrap(); } println!("Counter value: {}", *counter.lock().unwrap()); let shared_string = create_shared_data(String::from("Hello")); let handle = modify_shared_data(shared_string.clone(), |s| s.push_str(" World")); handle.join().unwrap(); println!("Modified string: {}", *shared_string.lock().unwrap());}use std::sync::{Arc, Mutex};use std::thread::{self, JoinHandle};pub fn create_shared_data<T>(initial: T) -> Arc<Mutex<T>> { // 1. Initialize and return a new Arc<Mutex<T>> with the initial value Arc::new(Mutex::new(initial))}pub fn increment_counter( counter: Arc<Mutex<i32>>, threads: usize, increments: usize,) -> Vec<JoinHandle<()>> { // 2. Increment the counter by the given increments using the given number of threads (0..threads).map( |_| { let m = Arc::clone(&counter); thread::spawn( move || { let mut c = m.lock().unwrap(); *c += increments as i32; } ) } ).collect()}pub fn modify_shared_data<T: Send + 'static>( data: Arc<Mutex<T>>, modifier: fn(&mut T),) -> JoinHandle<()> { // 3. Use a new thread to modify the shared data thread::spawn( move || { let a = Arc::clone(&data); let data: &mut T = &mut a.lock().unwrap(); modifier(data); } )}// Example usagepub fn main() { let counter = create_shared_data(0); let handles = increment_counter(Arc::clone(&counter), 5, 10); for handle in handles { handle.join().unwrap(); } println!("Counter value: {}", *counter.lock().unwrap()); let shared_string = create_shared_data(String::from("Hello")); let handle = modify_shared_data(shared_string.clone(), |s| s.push_str(" World")); handle.join().unwrap(); println!("Modified string: {}", *shared_string.lock().unwrap());}use std::sync::{Arc, Mutex};use std::thread::{self, JoinHandle};pub fn create_shared_data<T>(initial: T) -> Arc<Mutex<T>> { Arc::new(Mutex::new(initial)) // 1. Initialize and return a new Arc<Mutex<T>> with the initial value}pub fn increment_counter( counter: Arc<Mutex<i32>>, threads: usize, increments: usize,) -> Vec<JoinHandle<()>> { (0..threads) .map(|_| { let counter = Arc::clone(&counter); thread::spawn(move || { let mut guard = counter.lock().unwrap(); *guard += increments as i32; }) }) .collect()}pub fn modify_shared_data<T: Send + 'static>( data: Arc<Mutex<T>>, modifier: fn(&mut T),) -> JoinHandle<()> { thread::spawn(move || { let mut guard = data.lock().unwrap(); modifier(&mut guard); }) // 3. Use a new thread to modify the shared data}// Example usagepub fn main() { let counter = create_shared_data(0); let handles = increment_counter(Arc::clone(&counter), 5, 10); for handle in handles { handle.join().unwrap(); } println!("Counter value: {}", *counter.lock().unwrap()); let shared_string = create_shared_data(String::from("Hello")); let handle = modify_shared_data(shared_string.clone(), |s| s.push_str(" World")); handle.join().unwrap(); println!("Modified string: {}", *shared_string.lock().unwrap());}use std::sync::{Arc, Mutex};use std::thread::{self, JoinHandle};pub fn create_shared_data<T>(initial: T) -> Arc<Mutex<T>> { // 1. Initialize and return a new Arc<Mutex<T>> with the initial value Arc::new(Mutex::new(initial))}pub fn increment_counter( counter: Arc<Mutex<i32>>, threads: usize, increments: usize,) -> Vec<JoinHandle<()>> { // 2. Increment the counter by the given increments using the given number of threads let mut handles = Vec::new(); for _ in 0..threads { let count = Arc::clone(&counter); let handle = thread::spawn( move || { let mut num = count.lock().unwrap(); *num += increments as i32; } ); handles.push(handle); } handles}pub fn modify_shared_data<T: Send + 'static>( data: Arc<Mutex<T>>, modifier: fn(&mut T),) -> JoinHandle<()> { // 3. Use a new thread to modify the shared data let data_clone = Arc::clone(&data); let handle = thread::spawn( move || { let mut string_data = data_clone.lock().unwrap(); modifier(&mut string_data); } ); handle}// Example usagepub fn main() { let counter = create_shared_data(0); let handles = increment_counter(Arc::clone(&counter), 5, 10); for handle in handles { handle.join().unwrap(); } println!("Counter value: {}", *counter.lock().unwrap()); let shared_string = create_shared_data(String::from("Hello")); let handle = modify_shared_data(shared_string.clone(), |s| s.push_str(" World")); handle.join().unwrap(); println!("Modified string: {}", *shared_string.lock().unwrap());}use std::sync::{Arc, Mutex};use std::thread::{self, JoinHandle};pub fn create_shared_data<T>(initial: T) -> Arc<Mutex<T>> { Arc::new(Mutex::new(initial)) // 1. Initialize and return a new Arc<Mutex<T>> with the initial value}pub fn increment_counter( counter: Arc<Mutex<i32>>, threads: usize, increments: usize,) -> Vec<JoinHandle<()>> { (0..threads) .map(|_| { let counter = counter.clone(); std::thread::spawn(move || *counter.lock().expect("error") += increments as i32) }) .collect() // 2. Increment the counter by the given increments using the given number of threads}pub fn modify_shared_data<T: Send + 'static>( data: Arc<Mutex<T>>, modifier: fn(&mut T),) -> JoinHandle<()> { let handle = data.clone(); std::thread::spawn(move || modifier(&mut *handle.lock().expect("error on lock"))) // 3. Use a new thread to modify the shared data}// Example usagepub fn main() { let counter = create_shared_data(0); let handles = increment_counter(Arc::clone(&counter), 5, 10); for handle in handles { handle.join().unwrap(); } println!("Counter value: {}", *counter.lock().unwrap()); let shared_string = create_shared_data(String::from("Hello")); let handle = modify_shared_data(shared_string.clone(), |s| s.push_str(" World")); handle.join().unwrap(); println!("Modified string: {}", *shared_string.lock().unwrap());}use std::sync::{Arc, Mutex};use std::thread::{self, JoinHandle};pub fn create_shared_data<T>(initial: T) -> Arc<Mutex<T>> { // 1. Initialize and return a new Arc<Mutex<T>> with the initial value Arc::new(Mutex::new(initial))}pub fn increment_counter( counter: Arc<Mutex<i32>>, threads: usize, increments: usize,) -> Vec<JoinHandle<()>> { let mut handles = Vec::with_capacity(threads); for _i in 0..threads { let data = Arc::clone(&counter); let r = thread::spawn(move || { *data.lock().unwrap() += increments as i32; }); handles.push(r); } handles}pub fn modify_shared_data<T: Send + 'static>( data: Arc<Mutex<T>>, modifier: fn(&mut T),) -> JoinHandle<()> { thread::spawn(move || { modifier(&mut data.lock().unwrap()) })}// Example usagepub fn main() { let counter = create_shared_data(0); let handles = increment_counter(Arc::clone(&counter), 5, 10); for handle in handles { handle.join().unwrap(); } println!("Counter value: {}", *counter.lock().unwrap()); let shared_string = create_shared_data(String::from("Hello")); let handle = modify_shared_data(shared_string.clone(), |s| s.push_str(" World")); handle.join().unwrap(); println!("Modified string: {}", *shared_string.lock().unwrap());}use std::sync::{Arc, Mutex};use std::thread::{self, JoinHandle};pub fn create_shared_data<T>(initial: T) -> Arc<Mutex<T>> { Arc::new(Mutex::new(initial))}pub fn increment_counter( counter: Arc<Mutex<i32>>, threads: usize, increments: usize,) -> Vec<JoinHandle<()>> { (0..threads).map(|_| { let entry = Arc::clone(&counter); thread::spawn(move || { let mut entry = entry.lock().unwrap(); *entry += increments as i32; }) }).collect::<Vec<JoinHandle<()>>>()}pub fn modify_shared_data<T: Send + 'static>( data: Arc<Mutex<T>>, modifier: fn(&mut T),) -> JoinHandle<()> { thread::spawn(move || { modifier(&mut data.lock().unwrap()) })}// Example usagepub fn main() { let counter = create_shared_data(0); let handles = increment_counter(Arc::clone(&counter), 5, 10); for handle in handles { handle.join().unwrap(); } println!("Counter value: {}", *counter.lock().unwrap()); let shared_string = create_shared_data(String::from("Hello")); let handle = modify_shared_data(shared_string.clone(), |s| s.push_str(" World")); handle.join().unwrap(); println!("Modified string: {}", *shared_string.lock().unwrap());}use std::sync::{Arc, Mutex};use std::thread::{self, JoinHandle};pub fn create_shared_data<T>(initial: T) -> Arc<Mutex<T>> { Arc::new(Mutex::new(initial))}pub fn increment_counter( counter: Arc<Mutex<i32>>, threads: usize, increments: usize,) -> Vec<JoinHandle<()>> { (0..threads) .map(|_| { let counter_cloned = counter.clone(); thread::spawn(move || { *counter_cloned.lock().unwrap() += increments as i32; }) }) .collect()}pub fn modify_shared_data<T: Send + 'static>( data: Arc<Mutex<T>>, modifier: fn(&mut T),) -> JoinHandle<()> { thread::spawn(move || { let mut data_ref = data.lock().unwrap(); modifier(&mut *data_ref); })}// Example usagepub fn main() { let counter = create_shared_data(0); let handles = increment_counter(Arc::clone(&counter), 5, 10); for handle in handles { handle.join().unwrap(); } println!("Counter value: {}", *counter.lock().unwrap()); let shared_string = create_shared_data(String::from("Hello")); let handle = modify_shared_data(shared_string.clone(), |s| s.push_str(" World")); handle.join().unwrap(); println!("Modified string: {}", *shared_string.lock().unwrap());}use std::sync::{Arc, Mutex};use std::thread::{self, JoinHandle};pub fn create_shared_data<T>(initial: T) -> Arc<Mutex<T>> { Arc::new( Mutex::new(initial) )}pub fn increment_counter( counter: Arc<Mutex<i32>>, threads: usize, increments: usize,) -> Vec<JoinHandle<()>> { (0..threads) .map(|_| { let counter = counter.clone(); thread::spawn(move || { for _ in 0..increments { let mut x = counter.lock().unwrap(); *x += 1 } }) }) .collect()}pub fn modify_shared_data<T: Send + 'static>( data: Arc<Mutex<T>>, modifier: fn(&mut T),) -> JoinHandle<()> { // 3. Use a new thread to modify the shared data let data = data.clone(); thread::spawn(move || { let mut x = data.lock().unwrap(); modifier(&mut *x); })}// Example usagepub fn main() { let counter = create_shared_data(0); let handles = increment_counter(Arc::clone(&counter), 5, 10); for handle in handles { handle.join().unwrap(); } println!("Counter value: {}", *counter.lock().unwrap()); let shared_string = create_shared_data(String::from("Hello")); let handle = modify_shared_data(shared_string.clone(), |s| s.push_str(" World")); handle.join().unwrap(); println!("Modified string: {}", *shared_string.lock().unwrap());}use std::sync::{Arc, Mutex};use std::thread::{spawn, JoinHandle};pub fn create_shared_data<T>(initial: T) -> Arc<Mutex<T>> { // 1. Initialize and return a new Arc<Mutex<T>> with the initial value Arc::new(Mutex::new(initial))}pub fn increment_counter( counter: Arc<Mutex<i32>>, threads: usize, increments: usize,) -> Vec<JoinHandle<()>> { // 2. Increment the counter by the given increments using the given number of threads (0..threads) .map(|_| { let counter = counter.clone(); spawn(move || { for _ in 0..increments { let mut x = counter.lock().expect("oops"); *x += 1; } }) }) .collect()}pub fn modify_shared_data<T: Send + 'static>( data: Arc<Mutex<T>>, modifier: fn(&mut T),) -> JoinHandle<()> { // 3. Use a new thread to modify the shared data let data = data.clone(); spawn(move || { let mut x = data.lock().expect("oops"); modifier(&mut *x); })}// Example usagepub fn main() { let counter = create_shared_data(0); let handles = increment_counter(Arc::clone(&counter), 5, 10); for handle in handles { handle.join().unwrap(); } println!("Counter value: {}", *counter.lock().unwrap()); let shared_string = create_shared_data(String::from("Hello")); let handle = modify_shared_data(shared_string.clone(), |s| s.push_str(" World")); handle.join().unwrap(); println!("Modified string: {}", *shared_string.lock().unwrap());}use std::sync::{Arc, Mutex};use std::thread::{self, JoinHandle};use std::ops::Deref;use std::ops::DerefMut;pub fn create_shared_data<T>(initial: T) -> Arc<Mutex<T>> { // 1. Initialize and return a new Arc<Mutex<T>> with the initial value Arc::new(Mutex::new(initial))}pub fn increment_counter( counter: Arc<Mutex<i32>>, threads: usize, increments: usize,) -> Vec<JoinHandle<Arc<Mutex<i32>>>> { // 2. Increment the counter by the given increments using the given number of threads let mut result = vec![]; for i in 0..threads { let cloned = counter.clone(); for j in 0..increments { *counter.lock().unwrap().deref_mut() += 1; } result.push(thread::spawn(move|| cloned)) } result}pub fn modify_shared_data<T: Send + 'static>( data: Arc<Mutex<T>>, modifier: fn(&mut T),) -> JoinHandle<()> { // 3. Use a new thread to modify the shared data thread::spawn(move||modifier(&mut data.deref().lock().unwrap()))}// Example usagepub fn main() { let counter = create_shared_data(0); let handles = increment_counter(Arc::clone(&counter), 5, 10); for handle in handles { handle.join().unwrap(); } println!("Counter value: {}", *counter.lock().unwrap()); let shared_string = create_shared_data(String::from("Hello")); let handle = modify_shared_data(shared_string.clone(), |s| s.push_str(" World")); handle.join().unwrap(); println!("Modified string: {}", *shared_string.lock().unwrap());}use std::sync::{Arc, Mutex};use std::thread::{self, JoinHandle};pub fn create_shared_data<T>(initial: T) -> Arc<Mutex<T>> { Arc::new(Mutex::new(initial))}pub fn increment_counter( counter: Arc<Mutex<i32>>, threads: usize, increments: usize,) -> Vec<JoinHandle<()>> { (0..threads) .map(|_| { let counter = Arc::clone(&counter); thread::spawn(move || { for _ in 0..increments { let mut x = counter.lock().expect("oops"); *x += 1; } }) }) .collect()}pub fn modify_shared_data<T: Send + 'static>( data: Arc<Mutex<T>>, modifier: fn(&mut T),) -> JoinHandle<()> { thread::spawn(move || { modifier(data.lock().as_mut().expect("oops")); })}// Example usagepub fn main() { let counter = create_shared_data(0); let handles = increment_counter(Arc::clone(&counter), 5, 10); for handle in handles { handle.join().unwrap(); } println!("Counter value: {}", *counter.lock().unwrap()); let shared_string = create_shared_data(String::from("Hello")); let handle = modify_shared_data(shared_string.clone(), |s| s.push_str(" World")); handle.join().unwrap(); println!("Modified string: {}", *shared_string.lock().unwrap());}use std::sync::{Arc, Mutex};use std::thread::{self, JoinHandle};pub fn create_shared_data<T>(initial: T) -> Arc<Mutex<T>> { // 1. Initialize and return a new Arc<Mutex<T>> with the initial value Arc::new(Mutex::new(initial))}pub fn increment_counter( counter: Arc<Mutex<i32>>, threads: usize, increments: usize,) -> Vec<JoinHandle<()>> { // 2. Increment the counter by the given increments using the given number of threads let mut handles = Vec::new(); for _ in 0..threads { let counter_clone = Arc::clone(&counter); let handle = thread::spawn(move || { for _ in 0..increments { let mut num = counter_clone.lock().unwrap(); *num += 1; } }); handles.push(handle); } handles}pub fn modify_shared_data<T: Send + 'static>( data: Arc<Mutex<T>>, modifier: fn(&mut T),) -> JoinHandle<()> { // 3. Use a new thread to modify the shared data //let data_clone = Arc::clone(&data); let handle = thread::spawn(move || { let mut data = data.lock().unwrap(); modifier(&mut data); }); handle}// Example usagepub fn main() { let counter = create_shared_data(0); let handles = increment_counter(Arc::clone(&counter), 5, 10); for handle in handles { handle.join().unwrap(); } println!("Counter value: {}", *counter.lock().unwrap()); let shared_string = create_shared_data(String::from("Hello")); let handle = modify_shared_data(shared_string.clone(), |s| s.push_str(" World")); handle.join().unwrap(); println!("Modified string: {}", *shared_string.lock().unwrap());}use std::ops::DerefMut;use std::sync::{Arc, Mutex};use std::thread::{self, JoinHandle};pub fn create_shared_data<T>(initial: T) -> Arc<Mutex<T>> { Arc::new(Mutex::new(initial))}pub fn increment_counter( counter: Arc<Mutex<i32>>, threads: usize, increments: usize,) -> Vec<JoinHandle<()>> { let mut thvec = vec![]; for _ in 0..threads { let local_counter = Arc::clone(&counter); thvec.push(thread::spawn(move || { for _ in 0..increments { *local_counter.lock().unwrap() += 1; } })); } thvec}pub fn modify_shared_data<T: Send + 'static>( data: Arc<Mutex<T>>, modifier: fn(&mut T),) -> JoinHandle<()> { thread::spawn(move || modifier(data.lock().unwrap().deref_mut()))}// Example usagepub fn main() { let counter = create_shared_data(0); let handles = increment_counter(Arc::clone(&counter), 5, 10); for handle in handles { handle.join().unwrap(); } println!("Counter value: {}", *counter.lock().unwrap()); let shared_string = create_shared_data(String::from("Hello")); let handle = modify_shared_data(shared_string.clone(), |s| s.push_str(" World")); handle.join().unwrap(); println!("Modified string: {}", *shared_string.lock().unwrap());}use std::sync::{Arc, Mutex};use std::thread::{spawn, JoinHandle};pub fn create_shared_data<T>(initial: T) -> Arc<Mutex<T>> { // 1. Initialize and return a new Arc<Mutex<T>> with the initial value Arc::new(Mutex::new(initial))}pub fn increment_counter( counter: Arc<Mutex<i32>>, threads: usize, increments: usize,) -> Vec<JoinHandle<()>> { // 2. Increment the counter by the given increments using the given number of threads let mut handles: Vec<JoinHandle<()>> = vec![]; for _i in 0..threads { let arc = Arc::clone(&counter); handles.push( spawn(move || { *arc.lock().unwrap() += increments as i32; }) ) } handles}pub fn modify_shared_data<T: Send + 'static>( data: Arc<Mutex<T>>, modifier: fn(&mut T),) -> JoinHandle<()> { // 3. Use a new thread to modify the shared data let arc: Arc<Mutex<T>> = Arc::clone(&data); spawn(move || { let mut val = arc.lock().unwrap(); modifier(&mut val); })}// Example usagepub fn main() { let counter = create_shared_data(0); let handles = increment_counter(Arc::clone(&counter), 5, 10); for handle in handles { handle.join().unwrap(); } println!("Counter value: {}", *counter.lock().unwrap()); let shared_string = create_shared_data(String::from("Hello")); let handle = modify_shared_data(shared_string.clone(), |s| s.push_str(" World")); handle.join().unwrap(); println!("Modified string: {}", *shared_string.lock().unwrap());}use std::sync::{Arc, Mutex};use std::thread::{self, JoinHandle};pub fn create_shared_data<T>(initial: T) -> Arc<Mutex<T>> { // 1. Initialize and return a new Arc<Mutex<T>> with the initial value Arc::new(Mutex::new(initial))}pub fn increment_counter( counter: Arc<Mutex<i32>>, threads: usize, increments: usize,) -> Vec<JoinHandle<()>> { // 2. Increment the counter by the given increments using the given number of threads let mut res = vec![]; for i in 0..threads { let c = Arc::clone(&counter); res.push( thread::spawn( move || { for _ in 0..increments { let mut lock = c.lock().unwrap(); *lock += 1; } } ) ) } res}pub fn modify_shared_data<T: Send + 'static>( data: Arc<Mutex<T>>, modifier: fn(&mut T),) -> JoinHandle<()> { // 3. Use a new thread to modify the shared data thread::spawn(move || { let mut lock = data.lock().unwrap(); modifier(&mut *lock); })}// Example usagepub fn main() { let counter = create_shared_data(0); let handles = increment_counter(Arc::clone(&counter), 5, 10); for handle in handles { handle.join().unwrap(); } println!("Counter value: {}", *counter.lock().unwrap()); let shared_string = create_shared_data(String::from("Hello")); let handle = modify_shared_data(shared_string.clone(), |s| s.push_str(" World")); handle.join().unwrap(); println!("Modified string: {}", *shared_string.lock().unwrap());}use std::sync::{Arc, Mutex};use std::thread::{self, JoinHandle};pub fn create_shared_data<T>(initial: T) -> Arc<Mutex<T>> { Arc::new(Mutex::new(initial))}pub fn increment_counter( counter: Arc<Mutex<i32>>, threads: usize, increments: usize,) -> Vec<JoinHandle<()>> { (0..threads).map( |_| thread::spawn( { let counter = Arc::clone(&counter); move || { *counter.lock().unwrap() += increments as i32; } } ) ).collect()}pub fn modify_shared_data<T: Send + 'static>( data: Arc<Mutex<T>>, modifier: fn(&mut T),) -> JoinHandle<()> { thread::spawn( move || { modifier(&mut data.lock().unwrap()); } )}// Example usagepub fn main() { let counter = create_shared_data(0); let handles = increment_counter(Arc::clone(&counter), 5, 10); for handle in handles { handle.join().unwrap(); } println!("Counter value: {}", *counter.lock().unwrap()); let shared_string = create_shared_data(String::from("Hello")); let handle = modify_shared_data(shared_string.clone(), |s| s.push_str(" World")); handle.join().unwrap(); println!("Modified string: {}", *shared_string.lock().unwrap());}use std::sync::{Arc, Mutex};use std::thread::{self, JoinHandle};pub fn create_shared_data<T>(initial: T) -> Arc<Mutex<T>> { // 1. Initialize and return a new Arc<Mutex<T>> with the initial value Arc::new(Mutex::new(initial))}pub fn increment_counter( counter: Arc<Mutex<i32>>, threads: usize, increments: usize,) -> Vec<JoinHandle<()>> { // 2. Increment the counter by the given increments using the given number of threads let mut handles = vec![]; for _ in 0..threads { let counter = Arc::clone(&counter); let handle = thread::spawn(move || { for _ in 0..increments { let mut num = counter.lock().unwrap(); *num += 1; } }); handles.push(handle); } handles}pub fn modify_shared_data<T: Send + 'static>( data: Arc<Mutex<T>>, modifier: fn(&mut T),) -> JoinHandle<()> { // 3. Use a new thread to modify the shared data let data = Arc::clone(&data); thread::spawn(move || { let mut content = data.lock().unwrap(); modifier(&mut *content); })}// Example usagepub fn main() { let counter = create_shared_data(0); let handles = increment_counter(Arc::clone(&counter), 5, 10); for handle in handles { handle.join().unwrap(); } println!("Counter value: {}", *counter.lock().unwrap()); let shared_string = create_shared_data(String::from("Hello")); let handle = modify_shared_data(shared_string.clone(), |s| s.push_str(" World")); handle.join().unwrap(); println!("Modified string: {}", *shared_string.lock().unwrap());}use std::sync::{Arc, Mutex};use std::thread::{self, JoinHandle};pub fn create_shared_data<T>(initial: T) -> Arc<Mutex<T>> { Arc::new(Mutex::new(initial))}pub fn increment_counter( counter: Arc<Mutex<i32>>, threads: usize, increments: usize,) -> Vec<JoinHandle<()>> { (0..threads) .map(|_| counter.clone()) .map(|entry| thread::spawn(move || *entry.lock().unwrap() += increments as i32)) .collect::<Vec<JoinHandle<()>>>()}pub fn modify_shared_data<T: Send + 'static>( data: Arc<Mutex<T>>, modifier: fn(&mut T),) -> JoinHandle<()> { let data_clone = data.clone(); thread::spawn(move || { let mut _data = data_clone.lock().unwrap(); modifier(&mut *_data); })}// Example usagepub fn main() { let counter = create_shared_data(0); let handles = increment_counter(Arc::clone(&counter), 5, 10); for handle in handles { handle.join().unwrap(); } println!("Counter value: {}", *counter.lock().unwrap()); let shared_string = create_shared_data(String::from("Hello")); let handle = modify_shared_data(shared_string.clone(), |s| s.push_str(" World")); handle.join().unwrap(); println!("Modified string: {}", *shared_string.lock().unwrap());}use std::sync::{Arc, Mutex};use std::thread::{self, JoinHandle};pub fn create_shared_data<T>(initial: T) -> Arc<Mutex<T>> { Arc::new(Mutex::new(initial))}pub fn increment_counter( counter: Arc<Mutex<i32>>, threads: usize, increments: usize,) -> Vec<JoinHandle<()>> { let mut handles = vec![]; for _ in 0..threads { let counter_clone = counter.clone(); let join_handle = thread::spawn(move || { let mut _counter = counter_clone.lock().unwrap(); *_counter += increments as i32 }); handles.push(join_handle); } handles}pub fn modify_shared_data<T: Send + 'static>( data: Arc<Mutex<T>>, modifier: fn(&mut T),) -> JoinHandle<()> { let data_clone = data.clone(); thread::spawn(move || { let mut _data = data_clone.lock().unwrap(); modifier(&mut *_data); })}// Example usagepub fn main() { let counter = create_shared_data(0); let handles = increment_counter(Arc::clone(&counter), 5, 10); for handle in handles { handle.join().unwrap(); } println!("Counter value: {}", *counter.lock().unwrap()); let shared_string = create_shared_data(String::from("Hello")); let handle = modify_shared_data(shared_string.clone(), |s| s.push_str(" World")); handle.join().unwrap(); println!("Modified string: {}", *shared_string.lock().unwrap());}use std::sync::{Arc, Mutex};use std::thread::{self, JoinHandle};pub fn create_shared_data<T>(initial: T) -> Arc<Mutex<T>> { // 1. Initialize and return a new Arc<Mutex<T>> with the initial value Arc::new(Mutex::new(initial))}pub fn increment_counter( counter: Arc<Mutex<i32>>, threads: usize, increments: usize,) -> Vec<JoinHandle<()>> { // 2. Increment the counter by the given increments using the given number of threads (0..threads).map(|_| counter.clone()).map(|counter_copy| thread::spawn(move || { let mut entry = counter_copy.lock().unwrap(); *entry += increments as i32; })).collect::<Vec<JoinHandle<()>>>()}pub fn modify_shared_data<T: Send + 'static>( data: Arc<Mutex<T>>, modifier: fn(&mut T),) -> JoinHandle<()> { // 3. Use a new thread to modify the shared data let data = Arc::clone(&data); thread::spawn(move || { let mut entry = data.lock().unwrap(); modifier(&mut entry); })}// Example usagepub fn main() { let counter = create_shared_data(0); let handles = increment_counter(Arc::clone(&counter), 5, 10); for handle in handles { handle.join().unwrap(); } println!("Counter value: {}", *counter.lock().unwrap()); let shared_string = create_shared_data(String::from("Hello")); let handle = modify_shared_data(shared_string.clone(), |s| s.push_str(" World")); handle.join().unwrap(); println!("Modified string: {}", *shared_string.lock().unwrap());}use std::sync::{Arc, Mutex};use std::thread::{self, JoinHandle};pub fn create_shared_data<T>(initial: T) -> Arc<Mutex<T>> { // 1. Initialize and return a new Arc<Mutex<T>> with the initial value Arc::new(Mutex::new(initial))}pub fn increment_counter( counter: Arc<Mutex<i32>>, threads: usize, increments: usize,) -> Vec<JoinHandle<()>> { // 2. Increment the counter by the given increments using the given number of threads let mut handles = Vec::new(); for _ in 0..threads { let shared = Arc::clone(&counter); let handle = thread::spawn(move || { *shared.lock().unwrap() += increments as i32 }); handles.push(handle); } handles}pub fn modify_shared_data<T: Send + 'static>( data: Arc<Mutex<T>>, modifier: fn(&mut T),) -> JoinHandle<()> { // 3. Use a new thread to modify the shared data let shared = Arc::clone(&data); thread::spawn(move || { modifier(&mut shared.lock().unwrap()); })}// Example usagepub fn main() { let counter = create_shared_data(0); let handles = increment_counter(Arc::clone(&counter), 5, 10); for handle in handles { handle.join().unwrap(); } println!("Counter value: {}", *counter.lock().unwrap()); let shared_string = create_shared_data(String::from("Hello")); let handle = modify_shared_data(shared_string.clone(), |s| s.push_str(" World")); handle.join().unwrap(); println!("Modified string: {}", *shared_string.lock().unwrap());}