@@ -26,8 +26,8 @@ to help us make sense of code that can possibly be concurrent.
2626### ` Send `
2727
2828The first trait we're going to talk about is
29- [ ` Send ` ] ( ../std/marker/trait.Send.html ) . When a type ` T ` implements ` Send ` , it indicates
30- to the compiler that something of this type is able to have ownership transferred
29+ [ ` Send ` ] ( ../std/marker/trait.Send.html ) . When a type ` T ` implements ` Send ` , it
30+ indicates that something of this type is able to have ownership transferred
3131safely between threads.
3232
3333This is important to enforce certain restrictions. For example, if we have a
@@ -42,13 +42,19 @@ us enforce that it can't leave the current thread.
4242### ` Sync `
4343
4444The second of these traits is called [ ` Sync ` ] ( ../std/marker/trait.Sync.html ) .
45- When a type ` T ` implements ` Sync ` , it indicates to the compiler that something
45+ When a type ` T ` implements ` Sync ` , it indicates that something
4646of this type has no possibility of introducing memory unsafety when used from
47- multiple threads concurrently.
48-
49- For example, sharing immutable data with an atomic reference count is
50- threadsafe. Rust provides a type like this, ` Arc<T> ` , and it implements ` Sync ` ,
51- so it is safe to share between threads.
47+ multiple threads concurrently through shared references. This implies that
48+ types which don't have [ interior mutability] ( mutability.html ) are inherently
49+ ` Sync ` , which includes simple primitive types (like ` u8 ` ) and aggregate types
50+ containing them.
51+
52+ For sharing references across threads, Rust provides a wrapper type called
53+ ` Arc<T> ` . ` Arc<T> ` implements ` Send ` and ` Sync ` if and only if ` T ` implements
54+ both ` Send ` and ` Sync ` . For example, an object of type ` Arc<RefCell<U>> ` cannot
55+ be transferred across threads because
56+ [ ` RefCell ` ] ( choosing-your-guarantees.html#refcell%3Ct%3E ) does not implement
57+ ` Sync ` , consequently ` Arc<RefCell<U>> ` would not implement ` Send ` .
5258
5359These two traits allow you to use the type system to make strong guarantees
5460about the properties of your code under concurrency. Before we demonstrate
@@ -70,7 +76,7 @@ fn main() {
7076}
7177```
7278
73- The ` thread::spawn() ` method accepts a closure, which is executed in a
79+ The ` thread::spawn() ` method accepts a [ closure] ( closures.html ) , which is executed in a
7480new thread. It returns a handle to the thread, that can be used to
7581wait for the child thread to finish and extract its result:
7682
@@ -215,29 +221,18 @@ fn main() {
215221}
216222```
217223
224+ Note that the value of ` i ` is bound (copied) to the closure and not shared
225+ among the threads.
218226
219- If we'd tried to use ` Mutex<T> ` without wrapping it in an ` Arc<T> ` we would have
220- seen another error like:
221-
222- ``` text
223- error: the trait `core::marker::Send` is not implemented for the type `std::sync::mutex::MutexGuard<'_, collections::vec::Vec<u32>>` [E0277]
224- thread::spawn(move || {
225- ^~~~~~~~~~~~~
226- note: `std::sync::mutex::MutexGuard<'_, collections::vec::Vec<u32>>` cannot be sent between threads safely
227- thread::spawn(move || {
228- ^~~~~~~~~~~~~
229- ```
230-
231- You see, [ ` Mutex ` ] ( ../std/sync/struct.Mutex.html ) has a
232- [ ` lock ` ] ( ../std/sync/struct.Mutex.html#method.lock )
233- method which has this signature:
227+ Also note that [ ` lock ` ] ( ../std/sync/struct.Mutex.html#method.lock ) method of
228+ [ ` Mutex ` ] ( ../std/sync/struct.Mutex.html ) has this signature:
234229
235230``` ignore
236231fn lock(&self) -> LockResult<MutexGuard<T>>
237232```
238233
239- and because ` Send ` is not implemented for ` MutexGuard<T> ` , we couldn't have
240- transferred the guard across thread boundaries on it's own .
234+ and because ` Send ` is not implemented for ` MutexGuard<T> ` , the guard cannot
235+ cross thread boundaries, ensuring thread-locality of lock acquire and release .
241236
242237Let's examine the body of the thread more closely:
243238
@@ -317,22 +312,24 @@ use std::sync::mpsc;
317312fn main () {
318313 let (tx , rx ) = mpsc :: channel ();
319314
320- for _ in 0 .. 10 {
315+ for i in 0 .. 10 {
321316 let tx = tx . clone ();
322317
323318 thread :: spawn (move || {
324- let answer = 42 ;
319+ let answer = i * i ;
325320
326321 tx . send (answer );
327322 });
328323 }
329324
330- rx . recv (). ok (). expect (" Could not receive answer" );
325+ for _ in 0 .. 10 {
326+ println! (" {}" , rx . recv (). unwrap ());
327+ }
331328}
332329```
333330
334- A ` u32 ` is ` Send ` because we can make a copy. So we create a thread, ask it to calculate
335- the answer , and then it ` send() ` s us the answer over the channel.
331+ Here we create 10 threads, asking each to calculate the square of a number ( ` i `
332+ at the time of ` spawn() ` ) , and then ` send() ` back the answer over the channel.
336333
337334
338335## Panics
0 commit comments