<p dir="auto">Currently, the only Rust guide that talks about concurrency is the task guide, which talks about <code class="notranslate">spawn</code>, channels, Futures and Arcs and how to use them.</p>
<p dir="auto">However, Rusts concurrency story is not based on those library types, its based on its ownership and borrowing semantic and the two build-in traits <code class="notranslate">Send</code> and <code class="notranslate">Sync</code>.</p>
<p dir="auto">A rewritten concurrency guide could start by talking around the two core problems with concurrent/parallel code:</p>
<ol dir="auto">
<li>Making sure that objects created on one thread can be safely moved into another thread and then used there. (Examples: global allocator vs thread-local allocator, FFI bindings that need to stay on one thread)</li>
<li>Making sure that objects can be safely accessed from different threads in parallel. (Examples: worker threads with shared memory, global variables)</li>
</ol>
<p dir="auto">And then talk about how those two cases are, per definition, covered with the two build-in traits:</p>
<ol dir="auto">
<li><code class="notranslate">Send</code> expresses whether a type can be safely ownership-transferred across thread boundaries</li>
<li><code class="notranslate">Sync</code> expresses whether a  type can be safely accessed through shared references from different threads.</li>
</ol>
<p dir="auto">After each of these those two traits got explained, the guide could go into details about language semantics and std library APIs that make use of them, eg task spawning works with <code class="notranslate">Send</code>, <code class="notranslate">Arc</code>s are <code class="notranslate">Send</code> and  require <code class="notranslate">Sync</code> on the inner type, while channels are sendable endpoints that can only transfer sendable types, <code class="notranslate">static</code> variables that contain <code class="notranslate">Sync</code> types are safe to access, etc.</p>
<p dir="auto">At the introduction of <code class="notranslate">spawn</code>:</p>
<blockquote>
<p dir="auto">The spawn function has a very simple type signature: fn spawn(f: proc(): Send). Because it accepts only procs, and procs contain only owned data, spawn can safely move the entire proc and all its associated state into an entirely different task for execution. Like any closure, the function passed to spawn may capture an environment that it carries across tasks.</p>
</blockquote>
<p dir="auto">This doesn't explain what <code class="notranslate">Send</code> means, and instead talks about a simplified concept of owning the state. Something like this would be more correct (with the old <code class="notranslate">proc</code> closures):</p>
<blockquote>
<p dir="auto">The spawn function has a very simple type signature: fn spawn(f: proc():Send). A <code class="notranslate">proc</code> is a closure that captures its environment by value, and the <code class="notranslate">Send</code> bound restricts it to only allow the capture of sendable types, that is data that is safe to transfer across threads. Because all captured state is sendable, the closure is as well, and spawn can safely move the entire proc and all its associated state into an entirely different task for execution.</p>
</blockquote>
<p dir="auto">Then later in the <code class="notranslate">Arc</code> section, <code class="notranslate">Sync</code> is not mentioned at all. A possible introduction could look like this:</p>
<blockquote>
<p dir="auto">To tackle this issue, one can use an Atomically Reference Counted wrapper (Arc) as implemented in the sync library of Rust. With an Arc, the data will no longer be copied for each task. Instead, a single copy of the data exists that can be accessed through an Arc handle (Arc). This handle is send- and clonable, which means you can make as many of them as necessary and then send them to different tasks.</p>
<p dir="auto">However, for a given type <code class="notranslate">T</code> you are only allowed to construct an <code class="notranslate">Arc&lt;T&gt;</code> if <code class="notranslate">T</code> fulfills the <code class="notranslate">Sync</code> bound. <code class="notranslate">Sync</code>is a build-in trait the expresses that a type is thread safe to access through an shared reference, that is a <code class="notranslate">T</code> should only implement <code class="notranslate">Sync</code> if having two <code class="notranslate">&amp;T</code> in different threads that point to the same memory is safe. For the vast majority of types that are <code class="notranslate">Sync</code>, thread safety is given by simply not allowing any mutation through an shared reference, eg <code class="notranslate">u32</code> is <code class="notranslate">Share</code> because you can't mutate it through an <code class="notranslate">&amp;u32</code>.</p>
<p dir="auto">(Remaining examples of read-only Arc usage)</p>
<p dir="auto">Rust also enable safe mutation of data that is shared between threads, by providing library types that implement <code class="notranslate">Sync</code> and do some kind of runtime checking to safely pass out mutable reference one thread at a time. One example of this is the <code class="notranslate">Mutex&lt;T&gt;</code> type, which can be used to make any type <code class="notranslate">T</code> thread safe to access by using locks. For example you could construct an <code class="notranslate">Arc&lt;Mutex&lt;u32&gt;&gt;</code> to have an integer that can be shared and mutated across threads.</p>
</blockquote>