Skip to content

Commit b4f52cb

Browse files
jaystilemanyinsects
authored andcommitted
feat: Adding threads1.rs with a focus on JoinHandles and waiting for
spawned threads to finish. Moved the original threads1.rs to threads2.rs with the focus on the Mutex and modifying shared data. #892
1 parent 20024d4 commit b4f52cb

File tree

3 files changed

+69
-28
lines changed

3 files changed

+69
-28
lines changed

exercises/threads/threads1.rs

Lines changed: 19 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,31 @@
11
// threads1.rs
2-
// Make this compile! Execute `rustlings hint threads1` for hints :)
3-
// The idea is the thread spawned on line 22 is completing jobs while the main thread is
4-
// monitoring progress until 10 jobs are completed. Because of the difference between the
5-
// spawned threads' sleep time, and the waiting threads sleep time, when you see 6 lines
6-
// of "waiting..." and the program ends without timing out when running,
7-
// you've got it :)
2+
// Make this compile and run! Execute 'rustlings hint threads1' for hints :)
3+
// This program should wait until all the spawned threads have finished before exiting.
84

95
// I AM NOT DONE
106

11-
use std::sync::Arc;
127
use std::thread;
138
use std::time::Duration;
149

15-
struct JobStatus {
16-
jobs_completed: u32,
17-
}
1810

1911
fn main() {
20-
let status = Arc::new(JobStatus { jobs_completed: 0 });
21-
let status_shared = status.clone();
22-
thread::spawn(move || {
23-
for _ in 0..10 {
12+
13+
let mut handles = vec![];
14+
for i in 0..10 {
15+
thread::spawn(move || {
2416
thread::sleep(Duration::from_millis(250));
25-
status_shared.jobs_completed += 1;
26-
}
27-
});
28-
while status.jobs_completed < 10 {
29-
println!("waiting... ");
30-
thread::sleep(Duration::from_millis(500));
17+
println!("thread {} is complete", i);
18+
});
19+
}
20+
21+
let mut completed_threads = 0;
22+
for handle in handles {
23+
// TODO: a struct is returned from thread::spawn, can you use it?
24+
completed_threads += 1;
25+
}
26+
27+
if completed_threads != 10 {
28+
panic!("Oh no! All the spawned threads did not finish!");
3129
}
30+
3231
}

exercises/threads/threads2.rs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// threads2.rs
2+
// Make this compile! Execute `rustlings hint threads2` for hints :)
3+
// Building on the last exercise, we want all of the threads to complete their work but this time
4+
// the spawned threads need to be in charge of updating a shared value: JobStatus.jobs_completed
5+
6+
// I AM NOT DONE
7+
8+
use std::sync::Arc;
9+
use std::thread;
10+
use std::time::Duration;
11+
12+
struct JobStatus {
13+
jobs_completed: u32,
14+
}
15+
16+
fn main() {
17+
let status = Arc::new(JobStatus { jobs_completed: 0 });
18+
let mut handles = vec![];
19+
for _ in 0..10 {
20+
let status_shared = status.clone();
21+
let handle = thread::spawn(move || {
22+
thread::sleep(Duration::from_millis(250));
23+
// TODO: You must take an action before you update a shared value
24+
status_shared.jobs_completed += 1;
25+
});
26+
handles.push(handle);
27+
}
28+
for handle in handles {
29+
handle.join().unwrap();
30+
// TODO: Print the value of the JobStatus.jobs_completed. Did you notice anything
31+
// interesting in the output? Do you have to 'join' on all the handles?
32+
println!("jobs completed {}", ???);
33+
}
34+
}

info.toml

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -878,6 +878,22 @@ name = "threads1"
878878
path = "exercises/threads/threads1.rs"
879879
mode = "compile"
880880
hint = """
881+
`JoinHandle` is a struct that is returned from a spawned thread:
882+
https://doc.rust-lang.org/std/thread/fn.spawn.html
883+
884+
A challenge with multi-threaded applications is that the main thread can
885+
finish before the spawned threads are completed.
886+
https://doc.rust-lang.org/book/ch16-01-threads.html#waiting-for-all-threads-to-finish-using-join-handle
887+
888+
Collect the JoinHandles and wait for them to finish.
889+
https://doc.rust-lang.org/std/thread/struct.JoinHandle.html
890+
"""
891+
892+
[[exercises]]
893+
name = "threads2"
894+
path = "exercises/threads/threads2.rs"
895+
mode = "compile"
896+
hint = """
881897
`Arc` is an Atomic Reference Counted pointer that allows safe, shared access
882898
to **immutable** data. But we want to *change* the number of `jobs_completed`
883899
so we'll need to also use another type that will only allow one thread to
@@ -898,14 +914,6 @@ while they are sleeping, since this will prevent the other thread from
898914
being allowed to get the lock. Locks are automatically released when
899915
they go out of scope.
900916
901-
Ok, so, real talk, this was actually tricky for *me* to do too. And
902-
I could see a lot of different problems you might run into, so at this
903-
point I'm not sure which one you've hit :)
904-
905-
Please open an issue if you're still running into a problem that
906-
these hints are not helping you with, or if you've looked at the sample
907-
answers and don't understand why they work and yours doesn't.
908-
909917
If you've learned from the sample solutions, I encourage you to come
910918
back to this exercise and try it again in a few days to reinforce
911919
what you've learned :)"""

0 commit comments

Comments
 (0)