@@ -26,8 +26,8 @@ to help us make sense of code that can possibly be concurrent.
26
26
### ` Send `
27
27
28
28
The 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
31
31
safely between threads.
32
32
33
33
This 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.
42
42
### ` Sync `
43
43
44
44
The 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
46
46
of 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 ` .
52
58
53
59
These two traits allow you to use the type system to make strong guarantees
54
60
about the properties of your code under concurrency. Before we demonstrate
@@ -70,7 +76,7 @@ fn main() {
70
76
}
71
77
```
72
78
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
74
80
new thread. It returns a handle to the thread, that can be used to
75
81
wait for the child thread to finish and extract its result:
76
82
@@ -215,29 +221,18 @@ fn main() {
215
221
}
216
222
```
217
223
224
+ Note that the value of ` i ` is bound (copied) to the closure and not shared
225
+ among the threads.
218
226
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:
234
229
235
230
``` ignore
236
231
fn lock(&self) -> LockResult<MutexGuard<T>>
237
232
```
238
233
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 .
241
236
242
237
Let's examine the body of the thread more closely:
243
238
@@ -317,22 +312,24 @@ use std::sync::mpsc;
317
312
fn main () {
318
313
let (tx , rx ) = mpsc :: channel ();
319
314
320
- for _ in 0 .. 10 {
315
+ for i in 0 .. 10 {
321
316
let tx = tx . clone ();
322
317
323
318
thread :: spawn (move || {
324
- let answer = 42 ;
319
+ let answer = i * i ;
325
320
326
321
tx . send (answer );
327
322
});
328
323
}
329
324
330
- rx . recv (). ok (). expect (" Could not receive answer" );
325
+ for _ in 0 .. 10 {
326
+ println! (" {}" , rx . recv (). unwrap ());
327
+ }
331
328
}
332
329
```
333
330
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.
336
333
337
334
338
335
## Panics
0 commit comments