mirror of
https://github.com/darkicewolf50/RustBrock.git
synced 2025-06-15 04:54:17 -06:00
started ch16.3
This commit is contained in:
parent
661e8bf5c7
commit
96dbd779e7
40
.obsidian/workspace.json
vendored
40
.obsidian/workspace.json
vendored
@ -24,20 +24,6 @@
|
||||
{
|
||||
"id": "53b36d00b704136e",
|
||||
"type": "leaf",
|
||||
"state": {
|
||||
"type": "markdown",
|
||||
"state": {
|
||||
"file": "Smart Pointers.md",
|
||||
"mode": "source",
|
||||
"source": false
|
||||
},
|
||||
"icon": "lucide-file",
|
||||
"title": "Smart Pointers"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "feca3744741d15fc",
|
||||
"type": "leaf",
|
||||
"state": {
|
||||
"type": "markdown",
|
||||
"state": {
|
||||
@ -49,6 +35,20 @@
|
||||
"title": "Concurrency"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "3d0ca0b1691c4c2f",
|
||||
"type": "leaf",
|
||||
"state": {
|
||||
"type": "markdown",
|
||||
"state": {
|
||||
"file": "Shared State Concurrency.md",
|
||||
"mode": "source",
|
||||
"source": false
|
||||
},
|
||||
"icon": "lucide-file",
|
||||
"title": "Shared State Concurrency"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "b104e4647c0ac328",
|
||||
"type": "leaf",
|
||||
@ -245,10 +245,14 @@
|
||||
"command-palette:Open command palette": false
|
||||
}
|
||||
},
|
||||
"active": "feca3744741d15fc",
|
||||
"active": "3d0ca0b1691c4c2f",
|
||||
"lastOpenFiles": [
|
||||
"Smart Pointers.md",
|
||||
"Concurrency.md",
|
||||
"Shared State Concurrency.md",
|
||||
"Smart Pointers.md",
|
||||
"().md",
|
||||
"Simultaneous Code Running.md",
|
||||
"Passing Data Between Threads.md",
|
||||
"Leaky Reference Cycles.md",
|
||||
"Test Controls.md",
|
||||
"Ref Cell Mutability.md",
|
||||
@ -270,10 +274,6 @@
|
||||
"Lifetimes.md",
|
||||
"2025-02-04.md",
|
||||
"data_types.md",
|
||||
"Collection of Common Data Structs.md",
|
||||
"Constants.md",
|
||||
"Crates.md",
|
||||
"Data Types.md",
|
||||
"does_not_compile.svg",
|
||||
"Untitled.canvas",
|
||||
"Good and Bad Code/Commenting Pratices",
|
||||
|
@ -1 +1,72 @@
|
||||
# Shared-State Concurrency
|
||||
# Shared-State Concurrency
|
||||
Message passing is not the only way of handling concurrency.
|
||||
|
||||
Another way would be multiple threads to access the same shared data.
|
||||
|
||||
Consider this part of the slogan form the Go language documentation:
|
||||
|
||||
"Do not communicate by sharing memory."
|
||||
|
||||
What would communicating by sharing memory look like?
|
||||
|
||||
Why would message-passing enthusiasts caution not to use memory sharing.
|
||||
|
||||
Channels in any programming language are similar to single ownership, because once you transfer a value down a channel, you should no longer use that value.
|
||||
|
||||
Shared memory concurrency is like multiple ownership: multiple threads can access the same memory location at the same time.
|
||||
|
||||
As we saw before [Ch15](./Smart%20Pointers.md), where smart pointers made multiple ownership possible.
|
||||
|
||||
This can add complexity because these different owners need managing.
|
||||
|
||||
Rust's type system and ownership rules majority assist in getting this management correct.
|
||||
|
||||
Lets look at one example mutexes, one of the more common concurrency primitives for shared memory.
|
||||
|
||||
## Using Mutexes to Allow Access to Data from One Thread at a Time
|
||||
*Mutex* is an abbreviation for *mutual exclusion*, as in, a mutex allows only one thread to access some data at any given time.
|
||||
|
||||
To access the data in a mutex, a thread must first signal that it wants access by asking to acquire the mutex's *lock*.
|
||||
|
||||
The lock is a data structure that is part of the mutex that keeps track of who is currently gas exclusive access to the data.
|
||||
|
||||
The mutex can be described as *guarding* the data it holds via the locking system.
|
||||
|
||||
Mutexes have an associated reputation for being difficult to use because to must remember two rules:
|
||||
- You must attempt to acquire the lock before using the data
|
||||
- When you are done with the data that the mutex guards, you must unlock the data so other threads can acquire the lock
|
||||
|
||||
A real-world metaphor for a mutex would be like imagining a panel discussion at a conference with only one microphone.
|
||||
|
||||
Before a panelist can speak, they have to ask or signal that they want to use the microphone.
|
||||
|
||||
When they get the microphone, they can talk for as long as they want to and then hand the microphone to the next panelist who requests to speak.
|
||||
|
||||
If a panelist forgets to hand off the microphone off when they they are finished with it, no one else is able to speak.
|
||||
|
||||
If management of the shared microphone goes wrong, the panel won't work as planned.
|
||||
|
||||
Management of mutexes can be incredibly tricky to get right.
|
||||
|
||||
This is why so many people are enthusiastic about channels.
|
||||
|
||||
However due to Rust's type system and ownership rules, you can't get locking and unlocking wrong.
|
||||
|
||||
### The API of `Mutex<T>`
|
||||
Here is an example of how to use a mutex.
|
||||
|
||||
We will start by using a mutex in a single threaded context.
|
||||
```rust
|
||||
use std::sync::Mutex;
|
||||
|
||||
fn main() {
|
||||
let m = Mutex::new(5);
|
||||
|
||||
{
|
||||
let mut num = m.lock().unwrap();
|
||||
*num = 6;
|
||||
}
|
||||
|
||||
println!("m = {m:?}");
|
||||
}
|
||||
```
|
||||
|
Loading…
x
Reference in New Issue
Block a user