rust: move concurrency notes to own file

This commit is contained in:
Marcello 2024-04-14 13:40:01 +02:00
parent ac4ac7f821
commit f499c7b22b
3 changed files with 89 additions and 50 deletions

View file

@ -1492,56 +1492,6 @@ Rust's memory safety guarantees make it difficult, but not impossible, to accide
Rust allows memory leaks by using `Rc<T>` and `RefCell<T>`: it's possible to create references where items refer to each other in a cycle.
This creates memory leaks because the reference count of each item in the cycle will never reach 0, and the values will never be dropped.
## Concurrency
### Creating Threads
The `thread::spawn` function creates a new tread that will execute the passed closure. Any data captured by the closure is *moved* to the capturing thread.
The thread's **handle** can be used to wait for completion and retieve the computation result or errors if any.
```rs linenums="1"
// if no data is captured the move keyword can be removed
let handle = std::thread::spawn(move || { /* ... */ });
handle.join().unwrap();
```
> **Note**: a thread's execution can be termiated early if it's not joined and the main process terminates before the thread had completed it's work.
> **Note**: if a thread panics the handle will return the panic message so that it can be handled.
### Channels
To accomplish message-sending concurrently Rust's standard library provides an implementation of *channels*.
A **channel** is a general programming concept by which data is sent from one thread to another.
```rs linenums="1"
let (sender, receiver) = std::sync::mpsc::channel(); // the sender can be cloned to create multiple transmitters
let sender_1 = sender.clone();
std::thread::spawn(move || {
// send takes ownership of the message (moved to receiver scope)
sender_1.send("hello".to_owned()).unwrap();
});
let sender_2 = sender.clone();
std::thread::spawn(move || {
sender_2.send("hello".to_owned()).unwrap();
sender_2.send("world".to_owned()).unwrap();
sender_2.send("from".to_owned()).unwrap();
sender_2.send("thread".to_owned()).unwrap();
});
let message = receiver.recv().unwrap(); // receive a single value
// or
for message in receiver { } // receive multiple values (iteration stops when channel closes)
```
### `Send` & `Sync`
The `Send` marker trait indicates that ownership of values of the type implementing `Send` can be transferred between threads. Any type composed entirely of `Send` types is automatically marked as `Send`. Almost all primitive types are `Send`, aside from raw pointers.
The `Sync` marker trait indicates that it is safe for the type implementing `Sync` to be referenced from multiple threads. In other words, any type `T` is `Sync` if `&T` (an immutable reference to `T`) is `Send`, meaning the reference can be sent safely to another thread. Similar to `Send`, primitive types are `Sync`, and types composed entirely of types that are `Sync`are also `Sync`.
## Files
### Reading Files