1
0
mirror of https://github.com/google/comprehensive-rust.git synced 2025-04-02 17:48:47 +02:00

concurrency: Add detailed teaching notes for welcome and threads slides ()

These follow the flow of what I actually teach, which spends a
significant amount of time on the latter slide. I think it's worthwhile
to have a real flow documented in the teaching notes, both to make sure
nothing gets forgotten and to structure the experience of teaching.
This commit is contained in:
Frances Wingerter 2024-03-06 21:11:52 +00:00 committed by GitHub
parent 429694fa63
commit 976f6f6f24
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 46 additions and 7 deletions

@ -11,3 +11,13 @@ channels.
The Rust type system plays an important role in making many concurrency bugs The Rust type system plays an important role in making many concurrency bugs
compile time bugs. This is often referred to as _fearless concurrency_ since you compile time bugs. This is often referred to as _fearless concurrency_ since you
can rely on the compiler to ensure correctness at runtime. can rely on the compiler to ensure correctness at runtime.
<details>
- Rust lets us access OS concurrency toolkit: threads, sync. primitives, etc.
- The type system gives us safety for concurrency without any special features.
- The same tools that help with "concurrent" access in a single thread (e.g., a
called function that might mutate an argument or save references to it to read
later) save us from multi-threading issues.
</details>

@ -27,19 +27,48 @@ fn main() {
<details> <details>
Key points: - Rust thread APIs look not too different from e.g. C++ ones.
- Notice that the thread is stopped before it reaches 10 --- the main thread is - Run the example.
not waiting. - 5ms timing is loose enough that main and spawned threads stay mostly in
lockstep.
- Notice that the program ends before the spawned thread reaches 10!
- This is because main ends the program and spawned threads do not make it
persist.
- Compare to pthreads/C++ std::thread/boost::thread if desired.
- How do we wait around for the spawned thread to complete?
- [`thread::spawn`] returns a `JoinHandle`. Look at the docs.
- `JoinHandle` has a [`.join()`] method that blocks.
- Use `let handle = thread::spawn(...)` and later `handle.join()` to wait for - Use `let handle = thread::spawn(...)` and later `handle.join()` to wait for
the thread to finish. the thread to finish and have the program count all the way to 10.
- Trigger a panic in the thread, notice how this doesn't affect `main`. - Now what if we want to return a value?
- Look at docs again:
- [`thread::spawn`]'s closure returns `T`
- `JoinHandle` [`.join()`] returns `thread::Result<T>`
- Use the `Result` return value from `handle.join()` to get access to the panic - Use the `Result` return value from `handle.join()` to get access to the
payload. This is a good time to talk about [`Any`]. returned value.
- Ok, what about the other case?
- Trigger a panic in the thread. Note that this doesn't panic `main`.
- Access the panic payload. This is a good time to talk about [`Any`].
- Now we can return values from threads! What about taking inputs?
- Capture something by reference in the thread closure.
- An error message indicates we must move it.
- Move it in, see we can compute and then return a derived value.
- If we want to borrow?
- Main kills child threads when it returns, but another function would just
return and leave them running.
- That would be stack use-after-return, which violates memory safety!
- How do we avoid this? see next slide.
[`Any`]: https://doc.rust-lang.org/std/any/index.html [`Any`]: https://doc.rust-lang.org/std/any/index.html
[`thread::spawn`]: https://doc.rust-lang.org/std/thread/fn.spawn.html
[`.join()`]: https://doc.rust-lang.org/std/thread/struct.JoinHandle.html#method.join
</details> </details>