threads2 solution

This commit is contained in:
mo8it 2024-07-01 11:11:11 +02:00
parent b000164eed
commit dfa2b44f71
3 changed files with 59 additions and 20 deletions

View file

@ -1,35 +1,34 @@
// Building on the last exercise, we want all of the threads to complete their // Building on the last exercise, we want all of the threads to complete their
// work but this time the spawned threads need to be in charge of updating a // work. But this time, the spawned threads need to be in charge of updating a
// shared value: JobStatus.jobs_completed // shared value: `JobStatus.jobs_done`
use std::sync::Arc; use std::{sync::Arc, thread, time::Duration};
use std::thread;
use std::time::Duration;
struct JobStatus { struct JobStatus {
jobs_completed: u32, jobs_done: u32,
} }
fn main() { fn main() {
// TODO: `Arc` isn't enough if you want a **mutable** shared state // TODO: `Arc` isn't enough if you want a **mutable** shared state.
let status = Arc::new(JobStatus { jobs_completed: 0 }); let status = Arc::new(JobStatus { jobs_done: 0 });
let mut handles = vec![]; let mut handles = Vec::new();
for _ in 0..10 { for _ in 0..10 {
let status_shared = Arc::clone(&status); let status_shared = Arc::clone(&status);
let handle = thread::spawn(move || { let handle = thread::spawn(move || {
thread::sleep(Duration::from_millis(250)); thread::sleep(Duration::from_millis(250));
// TODO: You must take an action before you update a shared value
status_shared.jobs_completed += 1; // TODO: You must take an action before you update a shared value.
status_shared.jobs_done += 1;
}); });
handles.push(handle); handles.push(handle);
} }
// Waiting for all jobs to complete // Waiting for all jobs to complete.
for handle in handles { for handle in handles {
handle.join().unwrap(); handle.join().unwrap();
} }
// TODO: Print the value of `JobStatus.jobs_completed` // TODO: Print the value of `JobStatus.jobs_done`.
println!("Jobs completed: {}", ???); println!("Jobs done: {}", todo!());
} }

View file

@ -1051,19 +1051,19 @@ dir = "20_threads"
test = false test = false
hint = """ hint = """
`Arc` is an Atomic Reference Counted pointer that allows safe, shared access `Arc` is an Atomic Reference Counted pointer that allows safe, shared access
to **immutable** data. But we want to *change* the number of `jobs_completed` to **immutable** data. But we want to *change* the number of `jobs_done` so
so we'll need to also use another type that will only allow one thread to we'll need to also use another type that will only allow one thread to mutate
mutate the data at a time. Take a look at this section of the book: the data at a time. Take a look at this section of the book:
https://doc.rust-lang.org/book/ch16-03-shared-state.html#atomic-reference-counting-with-arct https://doc.rust-lang.org/book/ch16-03-shared-state.html#atomic-reference-counting-with-arct
Keep reading if you'd like more hints :) Keep reading if you'd like more hints :)
Do you now have an `Arc<Mutex<JobStatus>>` at the beginning of `main`? Like: Do you now have an `Arc<Mutex<JobStatus>>` at the beginning of `main`? Like:
``` ```
let status = Arc::new(Mutex::new(JobStatus { jobs_completed: 0 })); let status = Arc::new(Mutex::new(JobStatus { jobs_done: 0 }));
``` ```
Similar to the code in the following example in the book: Similar to the code in the following example in The Book:
https://doc.rust-lang.org/book/ch16-03-shared-state.html#sharing-a-mutext-between-multiple-threads""" https://doc.rust-lang.org/book/ch16-03-shared-state.html#sharing-a-mutext-between-multiple-threads"""
[[exercises]] [[exercises]]

View file

@ -1 +1,41 @@
// Solutions will be available before the stable release. Thank you for testing the beta version 🥰 // Building on the last exercise, we want all of the threads to complete their
// work. But this time, the spawned threads need to be in charge of updating a
// shared value: `JobStatus.jobs_done`
use std::{
sync::{Arc, Mutex},
thread,
time::Duration,
};
struct JobStatus {
jobs_done: u32,
}
fn main() {
// `Arc` isn't enough if you want a **mutable** shared state.
// We need to wrap the value with a `Mutex`.
let status = Arc::new(Mutex::new(JobStatus { jobs_done: 0 }));
// ^^^^^^^^^^^ ^
let mut handles = Vec::new();
for _ in 0..10 {
let status_shared = Arc::clone(&status);
let handle = thread::spawn(move || {
thread::sleep(Duration::from_millis(250));
// Lock before you update a shared value.
status_shared.lock().unwrap().jobs_done += 1;
// ^^^^^^^^^^^^^^^^
});
handles.push(handle);
}
// Waiting for all jobs to complete.
for handle in handles {
handle.join().unwrap();
}
println!("Jobs done: {}", status.lock().unwrap().jobs_done);
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
}