85 lines
6.4 KiB
HTML
85 lines
6.4 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="en">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<title>Extensible Concurrency with Send and Sync</title>
|
||
</head>
|
||
<body>
|
||
<!-- Old headings. Do not remove or links may break. -->
|
||
<p><a id="extensible-concurrency-with-the-sync-and-send-traits"></a>
|
||
<a id="extensible-concurrency-with-the-send-and-sync-traits"></a></p>
|
||
<h2 id="extensible-concurrency-with-send-and-sync"><a class="header" href="#extensible-concurrency-with-send-and-sync">Extensible Concurrency with <code>Send</code> and <code>Sync</code></a></h2>
|
||
<p>Interestingly, almost every concurrency feature we’ve talked about so far in
|
||
this chapter has been part of the standard library, not the language. Your
|
||
options for handling concurrency are not limited to the language or the
|
||
standard library; you can write your own concurrency features or use those
|
||
written by others.</p>
|
||
<p>However, among the key concurrency concepts that are embedded in the language
|
||
rather than the standard library are the <code>std::marker</code> traits <code>Send</code> and <code>Sync</code>.</p>
|
||
<!-- Old headings. Do not remove or links may break. -->
|
||
<p><a id="allowing-transference-of-ownership-between-threads-with-send"></a></p>
|
||
<h3 id="transferring-ownership-between-threads"><a class="header" href="#transferring-ownership-between-threads">Transferring Ownership Between Threads</a></h3>
|
||
<p>The <code>Send</code> marker trait indicates that ownership of values of the type
|
||
implementing <code>Send</code> can be transferred between threads. Almost every Rust type
|
||
implements <code>Send</code>, but there are some exceptions, including <code>Rc<T></code>: This
|
||
cannot implement <code>Send</code> because if you cloned an <code>Rc<T></code> value and tried to
|
||
transfer ownership of the clone to another thread, both threads might update
|
||
the reference count at the same time. For this reason, <code>Rc<T></code> is implemented
|
||
for use in single-threaded situations where you don’t want to pay the
|
||
thread-safe performance penalty.</p>
|
||
<p>Therefore, Rust’s type system and trait bounds ensure that you can never
|
||
accidentally send an <code>Rc<T></code> value across threads unsafely. When we tried to do
|
||
this in Listing 16-14, we got the error <code>the trait `Send` is not implemented for `Rc<Mutex<i32>>`</code>. When we switched to <code>Arc<T></code>, which does implement
|
||
<code>Send</code>, the code compiled.</p>
|
||
<p>Any type composed entirely of <code>Send</code> types is automatically marked as <code>Send</code> as
|
||
well. Almost all primitive types are <code>Send</code>, aside from raw pointers, which
|
||
we’ll discuss in Chapter 20.</p>
|
||
<!-- Old headings. Do not remove or links may break. -->
|
||
<p><a id="allowing-access-from-multiple-threads-with-sync"></a></p>
|
||
<h3 id="accessing-from-multiple-threads"><a class="header" href="#accessing-from-multiple-threads">Accessing from Multiple Threads</a></h3>
|
||
<p>The <code>Sync</code> marker trait indicates that it is safe for the type implementing
|
||
<code>Sync</code> to be referenced from multiple threads. In other words, any type <code>T</code>
|
||
implements <code>Sync</code> if <code>&T</code> (an immutable reference to <code>T</code>) implements <code>Send</code>,
|
||
meaning the reference can be sent safely to another thread. Similar to <code>Send</code>,
|
||
primitive types all implement <code>Sync</code>, and types composed entirely of types that
|
||
implement <code>Sync</code> also implement <code>Sync</code>.</p>
|
||
<p>The smart pointer <code>Rc<T></code> also doesn’t implement <code>Sync</code> for the same reasons
|
||
that it doesn’t implement <code>Send</code>. The <code>RefCell<T></code> type (which we talked about
|
||
in Chapter 15) and the family of related <code>Cell<T></code> types don’t implement
|
||
<code>Sync</code>. The implementation of borrow checking that <code>RefCell<T></code> does at runtime
|
||
is not thread-safe. The smart pointer <code>Mutex<T></code> implements <code>Sync</code> and can be
|
||
used to share access with multiple threads, as you saw in <a href="ch16-03-shared-state.html#shared-access-to-mutext">“Shared Access to
|
||
<code>Mutex<T></code>”</a><!-- ignore -->.</p>
|
||
<h3 id="implementing-send-and-sync-manually-is-unsafe"><a class="header" href="#implementing-send-and-sync-manually-is-unsafe">Implementing <code>Send</code> and <code>Sync</code> Manually Is Unsafe</a></h3>
|
||
<p>Because types composed entirely of other types that implement the <code>Send</code> and
|
||
<code>Sync</code> traits also automatically implement <code>Send</code> and <code>Sync</code>, we don’t have to
|
||
implement those traits manually. As marker traits, they don’t even have any
|
||
methods to implement. They’re just useful for enforcing invariants related to
|
||
concurrency.</p>
|
||
<p>Manually implementing these traits involves implementing unsafe Rust code.
|
||
We’ll talk about using unsafe Rust code in Chapter 20; for now, the important
|
||
information is that building new concurrent types not made up of <code>Send</code> and
|
||
<code>Sync</code> parts requires careful thought to uphold the safety guarantees. <a href="../nomicon/index.html">“The
|
||
Rustonomicon”</a> has more information about these guarantees and how to
|
||
uphold them.</p>
|
||
<h2 id="summary"><a class="header" href="#summary">Summary</a></h2>
|
||
<p>This isn’t the last you’ll see of concurrency in this book: The next chapter
|
||
focuses on async programming, and the project in Chapter 21 will use the
|
||
concepts in this chapter in a more realistic situation than the smaller
|
||
examples discussed here.</p>
|
||
<p>As mentioned earlier, because very little of how Rust handles concurrency is
|
||
part of the language, many concurrency solutions are implemented as crates.
|
||
These evolve more quickly than the standard library, so be sure to search
|
||
online for the current, state-of-the-art crates to use in multithreaded
|
||
situations.</p>
|
||
<p>The Rust standard library provides channels for message passing and smart
|
||
pointer types, such as <code>Mutex<T></code> and <code>Arc<T></code>, that are safe to use in
|
||
concurrent contexts. The type system and the borrow checker ensure that the
|
||
code using these solutions won’t end up with data races or invalid references.
|
||
Once you get your code to compile, you can rest assured that it will happily
|
||
run on multiple threads without the kinds of hard-to-track-down bugs common in
|
||
other languages. Concurrent programming is no longer a concept to be afraid of:
|
||
Go forth and make your programs concurrent, fearlessly!</p>
|
||
</body>
|
||
</html>
|