Send & Sync
There are two special traits in Rust for concurrency semantics.
Sendmarks a structure safe to send between threads.Syncmarks a structure safe to share between threads.- (
&TisSend)
- (
These traits are what Rust uses to prevent data races.
They are automatically derived for all types if appropriate.
Automatically Derived
use std::thread; #[derive(Debug)] struct Thing; // Can send between threads! fn main() { let thing = Thing; thread::spawn(move || { println!("{:?}", thing); }).join().unwrap(); }
There are some notable types which are not Send or Sync.
Such as Rc, raw pointers, and UnsafeCell.
Example: Rc
use std::rc::Rc;
use std::thread;
// Does not work!
fn main() {
let value = Rc::new(true);
thread::spawn(move || {
println!("{:?}", value);
}).join().unwrap();
}
Example: Rc
error[E0277]: `Rc<bool>` cannot be sent between threads safely
--> src/main.rs:7:19
|
7 | thread::spawn(move || {
| ------------- ^------
| | |
| _____|_____________within this `{closure@src/main.rs:7:19: 7:26}`
| | |
| | required by a bound introduced by this call
8 | | println!("{:?}", value);
9 | | }).join().unwrap();
| |_____^ `Rc<bool>` cannot be sent between threads safely
|
= help: within `{closure@src/main.rs:7:19: 7:26}`, the trait `Send` is not implemented for `Rc<bool>`, which is required by `{closure@src/main.rs:7:19: 7:26}: Send`
note: required because it's used within this closure
--> src/main.rs:7:19
|
7 | thread::spawn(move || {
| ^^^^^^^
note: required by a bound in `spawn`
--> /home/mrg/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/thread/mod.rs:675:8
|
672 | pub fn spawn<F, T>(f: F) -> JoinHandle<T>
| ----- required by a bound in this function
...
675 | F: Send + 'static,
| ^^^^ required by this bound in `spawn`
For more information about this error, try `rustc --explain E0277`.
Implementing
It's possible to add the implementation of Send and Sync to a type.
#![allow(unused)] fn main() { struct Thing(*mut String); unsafe impl Send for Thing {} unsafe impl Sync for Thing {} }
In these cases, the task of thread safety is left to the implementor.
Relationships
If a type implements both Sync and Copy then it can also implement Send.
Relationships
A type &T can implement Send if the type T also implements Sync.
unsafe impl<'a, T: Sync + ?Sized> Send for &'a T {}
Relationships
A type &mut T can implement Send if the type T also implements Send.
unsafe impl<'a, T: Send + ?Sized> Send for &'a mut T {}
Consequences
What are the consequences of having Send and Sync?
Consequences
Carrying this information at the type system level allows driving data race bugs down to a compile time level.
Preventing this error class from reaching production systems.
Send and Sync are independent of the choice of concurrency (async, threaded, etc.).