### `Send`
The first trait we're going to talk about is
-[`Send`](../std/marker/trait.Send.html). When a type `T` implements `Send`, it indicates
-to the compiler that something of this type is able to have ownership transferred
+[`Send`](../std/marker/trait.Send.html). When a type `T` implements `Send`, it
+indicates that something of this type is able to have ownership transferred
safely between threads.
This is important to enforce certain restrictions. For example, if we have a
### `Sync`
The second of these traits is called [`Sync`](../std/marker/trait.Sync.html).
-When a type `T` implements `Sync`, it indicates to the compiler that something
+When a type `T` implements `Sync`, it indicates that something
of this type has no possibility of introducing memory unsafety when used from
-multiple threads concurrently.
-
-For example, sharing immutable data with an atomic reference count is
-threadsafe. Rust provides a type like this, `Arc<T>`, and it implements `Sync`,
-so it is safe to share between threads.
+multiple threads concurrently through shared references. This implies that
+types which don't have [interior mutability](mutability.html) are inherently
+`Sync`, which includes simple primitive types (like `u8`) and aggregate types
+containing them.
+
+For sharing references across threads, Rust provides a wrapper type called
+`Arc<T>`. `Arc<T>` implements `Send` and `Sync` if and only if `T` implements
+both `Send` and `Sync`. For example, an object of type `Arc<RefCell<U>>` cannot
+be transferred across threads because
+[`RefCell`](choosing-your-guarantees.html#refcell%3Ct%3E) does not implement
+`Sync`, consequently `Arc<RefCell<U>>` would not implement `Send`.
These two traits allow you to use the type system to make strong guarantees
about the properties of your code under concurrency. Before we demonstrate
}
```
-The `thread::spawn()` method accepts a closure, which is executed in a
+The `thread::spawn()` method accepts a [closure](closures.html), which is executed in a
new thread. It returns a handle to the thread, that can be used to
wait for the child thread to finish and extract its result:
}
```
+Note that the value of `i` is bound (copied) to the closure and not shared
+among the threads.
-If we'd tried to use `Mutex<T>` without wrapping it in an `Arc<T>` we would have
-seen another error like:
-
-```text
-error: the trait `core::marker::Send` is not implemented for the type `std::sync::mutex::MutexGuard<'_, collections::vec::Vec<u32>>` [E0277]
- thread::spawn(move || {
- ^~~~~~~~~~~~~
-note: `std::sync::mutex::MutexGuard<'_, collections::vec::Vec<u32>>` cannot be sent between threads safely
- thread::spawn(move || {
- ^~~~~~~~~~~~~
-```
-
-You see, [`Mutex`](../std/sync/struct.Mutex.html) has a
-[`lock`](../std/sync/struct.Mutex.html#method.lock)
-method which has this signature:
+Also note that [`lock`](../std/sync/struct.Mutex.html#method.lock) method of
+[`Mutex`](../std/sync/struct.Mutex.html) has this signature:
```ignore
fn lock(&self) -> LockResult<MutexGuard<T>>
```
-and because `Send` is not implemented for `MutexGuard<T>`, we couldn't have
-transferred the guard across thread boundaries on it's own.
+and because `Send` is not implemented for `MutexGuard<T>`, the guard cannot
+cross thread boundaries, ensuring thread-locality of lock acquire and release.
Let's examine the body of the thread more closely:
fn main() {
let (tx, rx) = mpsc::channel();
- for _ in 0..10 {
+ for i in 0..10 {
let tx = tx.clone();
thread::spawn(move || {
- let answer = 42;
+ let answer = i * i;
tx.send(answer);
});
}
- rx.recv().ok().expect("Could not receive answer");
+ for _ in 0..10 {
+ println!("{}", rx.recv().unwrap());
+ }
}
```
-A `u32` is `Send` because we can make a copy. So we create a thread, ask it to calculate
-the answer, and then it `send()`s us the answer over the channel.
+Here we create 10 threads, asking each to calculate the square of a number (`i`
+at the time of `spawn()`), and then `send()` back the answer over the channel.
## Panics