RustBrock/Sync and Send.md
darkicewolf50 6e94e27e06
Some checks failed
Test Gitea Actions / first (push) Successful in 17s
Test Gitea Actions / check-code (push) Failing after 15s
Test Gitea Actions / test (push) Has been skipped
Test Gitea Actions / documentation-check (push) Has been skipped
finished ch16.4 and ch16
2025-03-17 15:54:52 -06:00

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.