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 T
increment_counter
: Demonstrates multiple threads modifying shared statemodify_shared_data
: Generic function for thread-safe modificationsThe create_shared_data
function should:
T
Mutex
and Arc
The 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 'static
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); 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 let mut handles = vec![]; for _ in 0..threads { let counter = Arc::clone(&counter); let handle = thread::spawn( move || { let mut num = counter.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 inner_data = data.lock().unwrap(); modifier(&mut inner_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::new(); for _ in 0..threads { let counter = Arc::clone(&counter); handles.push(thread::spawn(move || { let mut data = counter.lock().unwrap(); *data += increments as i32; })) } handles}pub fn modify_shared_data<T: Send + 'static>( data: Arc<Mutex<T>>, modifier: fn(&mut T),) -> JoinHandle<()> { 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 (0..threads).into_iter() .map(|_| Arc::clone(&counter)) .map(|counter| { thread::spawn(move || { let mut data = counter.lock().unwrap(); *data += 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 = 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 (0..threads).map(|_| { let counter = counter.clone(); thread::spawn(move || { let mut counter_guard = counter.lock().unwrap(); *counter_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 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 (0..threads) .map(|_| Arc::clone(&counter)) .map(|counter| thread::spawn(move || { let mut counter = counter.lock().unwrap(); *counter += 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 = 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 threads_buf = vec![]; for _ in 0..threads { let c = counter.clone(); let t = thread::spawn(move || { *c.lock().unwrap() += increments as i32; }); threads_buf.push(t); } threads_buf}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 d = data.clone(); thread::spawn(move || { modifier(&mut d.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 ret:Vec<JoinHandle<()>> = Vec::with_capacity(threads); for _ in 0..threads { let cloned =Arc::clone(&counter); let handle = thread::spawn(move || { let mut x = cloned.lock().unwrap(); *x += increments as i32; }); ret.push(handle); } ret}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 || { let mut data = cloned.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::ops::DerefMut;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<JoinHandle<()>> = vec![]; for _ in 0..threads { let shared_counter = Arc::clone(&counter); let handle = thread::spawn(move || { let mut guard = shared_counter.lock().unwrap(); *guard += increments as i32; }); res.push(handle); } 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 || 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 counter=counter.clone(); thread::spawn(move || { let mut counter=counter.lock().unwrap(); *counter += 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 || 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<()>> { // 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 || { *counter.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<()> { let data_copy = Arc::clone(&data); thread::spawn(move || { modifier(&mut *data_copy.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<JoinHandle<()>> = vec![]; for _ in 0..threads { let counter = Arc::clone(&counter); handles.push( thread::spawn(move || { let mut counter = counter.lock().unwrap(); *counter += increments as i32; }) ) } return 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>> { 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 || { let mut counter = counter.lock().unwrap(); *counter += 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 = 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::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 spawned: Vec<JoinHandle<()>> = vec![]; for _ in 0..threads { let counter = Arc::clone(&counter); spawned.push(std::thread::spawn(move || { let mut counter = counter.lock().unwrap(); *counter += increments as i32; })); } spawned}pub fn modify_shared_data<T: Send + 'static>( data: Arc<Mutex<T>>, modifier: fn(&mut T),) -> JoinHandle<()> { std::thread::spawn(move || { let mut modify = data.lock().unwrap(); modifier(&mut modify); })}// 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 spawned_threads: Vec<JoinHandle<()>> = Vec::new(); for _ in 0..threads { // clone the Arc again here for each thread to resolve ownership issues let counter = Arc::clone(&counter); spawned_threads.push( thread::spawn(move || { // obtain the lock and unwrap let mut counter = counter.lock().unwrap(); // increment the counter by the given increments *counter += increments as i32; }) ); } spawned_threads}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 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>> { 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 || { *Arc::clone(&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>> { Arc::new(Mutex::new(initial))}pub fn increment_counter( counter: Arc<Mutex<i32>>, threads: usize, increments: usize,) -> Vec<JoinHandle<()>> { let mut v = Vec::<JoinHandle<()>>::new(); for _ in 0..threads { let ctr = counter.clone(); v.push(thread::spawn(move || { let mut c = ctr.lock().unwrap(); *c += increments as i32; })); } v}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>> { 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 += 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 = 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 (0..threads) .map(|_| { let counter = Arc::clone(&counter); thread::spawn(move || { let mut c = counter.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 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<JoinHandle<()>> = vec![]; for _ in 0..threads { let counter_clone = Arc::clone(&counter); let handle = thread::spawn(move || { *counter_clone.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 data_clone = Arc::clone(&data); thread::spawn(move || { modifier(&mut data_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};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<()>> { // 2. Increment the counter by the given increments using the given number of threads (0..threads).map(|thread_id| { thread::spawn({ let mut counter = counter.clone(); move || { let mut counter = counter.lock().unwrap(); *counter = *counter + 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({ let mut a = data.clone(); move || { modifier(a.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());}