mirror of
https://github.com/darkicewolf50/RustBrock.git
synced 2025-06-15 13:04:18 -06:00
57 lines
3.2 KiB
Markdown
57 lines
3.2 KiB
Markdown
# Extensible Concurrency with the `Sync` and `Send` Traits
|
|
The Rust language gas *very* few concurrency features.
|
|
|
|
Almost every feature we talked about so far has been part of the std library and not the language.
|
|
|
|
Your options for handling concurrency are not limited to the language or the std library; you are able to write your own concurrency features or use those written by others.
|
|
|
|
However, tow concurrency concepts that are embedded into the language are the `std::marker` traits `Sync` and `Send`.
|
|
|
|
## Allowing Transference of Ownership Between Threads with `Send`
|
|
The marker trait `Send` indicates that ownership of values of the type implemented `Send` can be transferred between threads.
|
|
|
|
Almost every Rust type is `Send`.
|
|
|
|
There are some exceptions, including `Rc<T>`.
|
|
|
|
This cannot be be `Send` because if you cloned a `Rc<T>` value and tried to transfer ownership of the clone to another thread, both threads might update the reference count at the same time.
|
|
|
|
This is the reason, `Rc<T>` is implemented for use in single-threaded situations where you don't want to pay the thread-safe performance penalty.
|
|
|
|
Rust's type system and trait bounds ensure that you can never accidentally send a `Rc<T>` value across threads unsafely.
|
|
|
|
When we tried to do this before we got the error: the trait `Send` is not implemented for `Rc<Mutex<i32>>`.
|
|
|
|
Any type composed entirely of `Send` types is automatically marked as `Send` as well.
|
|
|
|
Almost all primitives are `Send`, aside form raw pointers (This will be discussed in ch20).
|
|
|
|
## Allowing access form Multiple Threads with `Sync`
|
|
|
|
The `Sync` marker trait indicates that it is safe for the type implementing `Sync` to be referenced from multiple threads.
|
|
|
|
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`.
|
|
|
|
The smart pointer `Rc<T>` is not `Sync` as well for the same reasons that it is not `Send`.
|
|
|
|
The `RefCell<T>` types ([Ch15](./Smart%20Pointers.md)) and the family related to `Cell<T>` types are not `Sync`.
|
|
|
|
The implementation for borrow checking that `RefCell<T>` does at runtime is not thread-safe.
|
|
|
|
|
|
The smart pointer `Mutex<T>` is `Sync` and can be used to share access with multiple threads alike what we saw in ["Sharing a `Mutex<T>` Between Multiple Threads"](./Shared%20State%20Concurrency.md) Section.
|
|
|
|
## Implementing `Send` and `Sync` Manually is Unsafe
|
|
Because types that are made up of `Send` and `Sync` traits are also automatically `Send` and `Sync`, we don't need to implement these traits manually.
|
|
|
|
As marker traits they don't even have any methods to implement.
|
|
|
|
These are just useful for enforcing invariants related to concurrency.
|
|
|
|
Manually implemented these traits involves implementing unsafe Rust code (This will be discussed in Ch20).
|
|
|
|
For now the important information is that building new concurrent types not made up of `Send` and `Sync` parts requires careful thought to uphold the safety guarantees.
|
|
|
|
["The Rustonomicion"](https://doc.rust-lang.org/nomicon/index.html) has more information about these guarantees and how to uphold them. |