]> git.proxmox.com Git - rustc.git/blob - src/doc/book/second-edition/src/ch16-04-extensible-concurrency-sync-and-send.md
New upstream version 1.21.0+dfsg1
[rustc.git] / src / doc / book / second-edition / src / ch16-04-extensible-concurrency-sync-and-send.md
1 ## Extensible Concurrency with the `Sync` and `Send` Traits
2
3 One interesting aspect of Rust’s concurrency model is that the language knows
4 *very* little about concurrency. Almost everything we’ve been talking about so
5 far has been part of the standard library, not the language itself. Because we
6 don’t need the language to provide everything we need to program in a
7 concurrent context, we’re not limited to the concurrency options that the
8 standard library or language provide: we can write our own or use ones others
9 have written.
10
11 We said *almost* everything wasn’t in the language, so what is? There are two
12 traits, both in `std::marker`: `Sync` and `Send`.
13
14 ### `Send` for Indicating Ownership May Be Transferred to Another Thread
15
16 The `Send` marker trait indicates that ownership of that type may be
17 transferred between threads. Almost every Rust type is `Send`, but there are
18 some exceptions. One type provided by the standard library that is not `Send`
19 is `Rc<T>`: if we clone an `Rc<T>` value and try to transfer ownership of the
20 clone to another thread, both threads might update the reference count at the
21 same time. As we mentioned in the previous section, `Rc<T>` is implemented for
22 use in single-threaded situations where you don’t want to pay the performance
23 penalty of having a threadsafe reference count.
24
25 Because `Rc<T>` is not marked `Send`, Rust’s type system and trait bounds
26 ensure that we can never forget and accidentally send an `Rc<T>` value across
27 threads unsafely. We tried to do this in Listing 16-14, and we got an error
28 that said `the trait Send is not implemented for Rc<Mutex<i32>>`. When we
29 switched to `Arc<T>`, which is `Send`, the code compiled.
30
31 Any type that is composed entirely of `Send` types is automatically marked as
32 `Send` as well. Almost all primitive types are `Send`, aside from raw pointers,
33 which we’ll discuss in Chapter 19. Most standard library types are `Send`,
34 aside from `Rc<T>`.
35
36 ### `Sync` for Indicating Access from Multiple Threads is Safe
37
38 The `Sync` marker trait indicates that a type is safe to have references to a
39 value from multiple threads. Another way to say this is for any type `T`, `T`
40 is `Sync` if `&T` (a reference to `T`) is `Send` so that the reference can be
41 sent safely to another thread. In a similar manner as `Send`, primitive types
42 are `Sync` and types composed entirely of types that are `Sync` are also `Sync`.
43
44 `Rc<T>` is also not `Sync`, for the same reasons that it’s not `Send`.
45 `RefCell<T>` (which we talked about in Chapter 15) and the family of related
46 `Cell<T>` types are not `Sync`. The implementation of the borrow checking at
47 runtime that `RefCell<T>` does is not threadsafe. `Mutex<T>` is `Sync`, and can
48 be used to share access with multiple threads as we saw in the previous section.
49
50 ### Implementing `Send` and `Sync` Manually is Unsafe
51
52 Usually, we don’t need to implement the `Send` and `Sync` traits, since types
53 that are made up of `Send` and `Sync` traits are automatically also `Send` and
54 `Sync`. Because they’re marker traits, they don’t even have any methods to
55 implement. They’re just useful for enforcing concurrency-related invariants.
56
57 Implementing the guarantees that these traits are markers for involves
58 implementing unsafe Rust code. We’re going to be talking about using unsafe
59 Rust code in Chapter 19; for now, the important information is that building
60 new concurrent types that aren’t made up of `Send` and `Sync` parts requires
61 careful thought to make sure the safety guarantees are upheld. [The Nomicon]
62 has more information about these guarantees and how to uphold them.
63
64 [The Nomicon]: https://doc.rust-lang.org/stable/nomicon/
65
66 ## Summary
67
68 This isn’t the last time we’ll see concurrency in this book; the project in
69 Chapter 20 will use these concepts in a more realistic situation than the
70 smaller examples we discussed in this chapter.
71
72 As we mentioned, since very little of how Rust deals with concurrency has to be
73 part of the language, there are many concurrency solutions implemented as
74 crates. These evolve more quickly than the standard library; search online for
75 the current state-of-the-art crates for use in multithreaded situations.
76
77 Rust provides channels for message passing and smart pointer types like
78 `Mutex<T>` and `Arc<T>` that are safe to use in concurrent contexts. The type
79 system and the borrow checker will make sure the code we write using these
80 solutions won’t have data races or invalid references. Once we get our code
81 compiling, we can rest assured that our code will happily run on multiple
82 threads without the kinds of hard-to-track-down bugs common in other
83 programming languages. Concurrent programming is no longer something to be
84 afraid of: go forth and make your programs concurrent, fearlessly!
85
86 Next, let’s talk about idiomatic ways to model problems and structure solutions
87 as your Rust programs get bigger, and how Rust’s idioms relate to those you
88 might be familiar with from Object Oriented Programming.