Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,8 @@

- [The Rust runtime](runtime.md)

- [Concurrency](concurrency.md)

- [Appendices](appendices.md)
- [Grammar summary](grammar.md)
- [Macro Follow-Set Ambiguity Formal Specification](macro-ambiguity.md)
Expand Down
117 changes: 117 additions & 0 deletions src/concurrency.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
r[concurrency]
# Concurrency

r[concurrency.intro]
Rust provides language and library features for writing [concurrent programs]. These features are designed to prevent [data races] --- situations in which multiple threads access the same memory without proper synchronization, with at least one of the accesses modifying that memory.

This chapter describes the traits, types, and concepts that Rust uses to express and enforce safe concurrency.

r[concurrency.send-and-sync]
## Send and Sync

r[concurrency.send-and-sync.intro]
The [`Send`] and [`Sync`] [auto traits] are [unsafe traits] used by the Rust type system to track which types can be safely used across thread boundaries.

These traits are [marker traits] with no methods. Implementing them (whether manually or via the compiler's automatic implementation) asserts that a type has the intrinsic properties required for safe concurrent use.

Library functions that require types that can be sent across threads require [`Send`].
```rust
// This will compile successfully
// A type is `Send` if it can be safely transferred to another thread.
fn assert_send<T: Send>() {}

fn main() {
assert_send::<i32>(); // primitive types are Send
assert_send::<Vec<u8>>(); // Vec<T> is Send if T is Send
}
```

Something that awaits something that isn't sync will produce a [`core::future::Future`] that is not [`Send`].
```rust,compile_fail
// This will not compile
// A type containing `Rc<T>` is not `Send`.
use std::rc::Rc;

// This async function awaits something that uses an Rc (which is !Send)
async fn not_send_future() {
let rc = Rc::new(42);

// Simulate an async operation that captures `rc`
let _ = async {
println!("{}", rc);
}.await;
}

// A helper function that requires its argument to be Send
fn assert_send<T: Send>(_: T) {}

fn main() {
let fut = not_send_future();

assert_send(fut); //~ error[E0277] `*const i32` cannot be shared between threads safely
}
```

Library functions that require types that can be accessed concurrently from multiple threads require [`Sync`].
```rust
// This will compile successfully
// A type is `Sync` if it can be safely referenced from multiple threads.
fn assert_sync<T: Sync>() {}

fn main() {
assert_sync::<i32>(); // i32 is Sync
assert_sync::<&'static str>(); // string slices are Sync
assert_sync::<std::sync::Arc<i32>>(); // Arc<T> is Sync if T is Sync
}
```

```rust,compile_fail
// This will not compile
// A type containing `Cell<T>` is not `Sync`.
use std::cell::Cell;

fn assert_sync<T: Sync>() {}

fn main() {
assert_sync::<Cell<i32>>(); //~ error[E0277] `*const i32` cannot be shared between threads safely
}
```

r[concurrency.atomics]
## Atomics

r[concurrency.atomics.intro]
[Atomic types] allow multiple threads to safely read and write shared values without using explicit locks by providing atomic operations such as atomic loads, stores, and read-modify-write with configurable memory ordering.

```rust
use std::sync::atomic::{AtomicUsize, Ordering};
use std::thread;

fn main() {
static COUNTER: AtomicUsize = AtomicUsize::new(0);

let handles: Vec<_> = (0..10)
.map(|_| {
thread::spawn(|| {
for _ in 0..1000 {
COUNTER.fetch_add(1, Ordering::Relaxed);
}
})
})
.collect();

for handle in handles {
handle.join().unwrap();
}
}
```

[concurrent programs]: glossary.md#concurrent-program
[data races]: glossary.md#data-race
[`Send`]: special-types-and-traits.md#send
[`Sync`]: special-types-and-traits.md#sync
[auto traits]: special-types-and-traits.md#auto-traits
[unsafe traits]: items/traits.md#unsafe-traits
[marker traits]: glossary.md#marker-trait
[`core::future::Future`]: https://doc.rust-lang.org/stable/core/future/trait.Future.html
[Atomic types]: glossary.md#atomic-types
18 changes: 18 additions & 0 deletions src/glossary.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ items are defined in [implementations] and declared in [traits]. Only
functions, constants, and type aliases can be associated. Contrast to a [free
item].

### Atomic types

Atomic types provide primitive shared-memory communication between threads, and are the building blocks of other concurrent types.

### Blanket implementation

Any implementation where a type appears [uncovered](#uncovered-type). `impl<T> Foo
Expand All @@ -50,6 +54,10 @@ Combinators are higher-order functions that apply only functions and
earlier defined combinators to provide a result from its arguments.
They can be used to manage control flow in a modular fashion.

### Concurrent program

A concurrent program is a program that can perform multiple tasks or processes at the same time, possibly overlapping in execution.

### Crate

A crate is the unit of compilation and linking. There are different [types of
Expand All @@ -60,6 +68,10 @@ may be made visible to other crates by marking them as public in the crate
root, including through [paths] of public modules.
[More][crate].

### Data race

A data race occurs when multiple threads attempt to access the same shared memory location concurrently.

### Dispatch

Dispatch is the mechanism to determine which specific version of code is actually run when it involves polymorphism. Two major forms of dispatch are static dispatch and dynamic dispatch. Rust supports dynamic dispatch through the use of [trait objects][type.trait-object].
Expand Down Expand Up @@ -137,6 +149,12 @@ This is not affected by applied type arguments. `struct Foo` is considered local
`Vec<Foo>` is not. `LocalType<ForeignType>` is local. Type aliases do not
affect locality.

### Marker trait
A trait that has no associated items (no methods, no associated types, and no constants)
and is used only to mark that a type has a particular property.
Implementing a marker trait does not change a type’s behavior at runtime;
it simply communicates to the compiler and to other code that the type satisfies some condition.

### Module

A module is a container for zero or more [items]. Modules are organized in a
Expand Down