Extensible Concurrency with the Send
and Sync
Traits
Rust’s concurrency safety is enforced through two marker traits: Send
and Sync
. These traits are implemented automatically for most types but can be manually implemented for custom concurrent types.
The Send
Trait
Send
indicates that ownership of a type can be transferred between threads safely. Almost all Rust types implement Send
, with notable exceptions:
Rc<T>
: NotSend
because non-atomic reference counting creates race conditions- Raw pointers: Lack safety guarantees
Types composed entirely of Send
types automatically implement Send
. When we attempted to send Rc<Mutex<i32>>
between threads in Listing 16-14, the compiler prevented this due to Rc<T>
’s lack of Send
implementation.
The Sync
Trait
Sync
indicates that a type is safe to access from multiple threads simultaneously. A type T
implements Sync
if &T
(an immutable reference to T
) implements Send
.
Types that don’t implement Sync
:
Rc<T>
: Non-atomic reference counting unsafe for concurrent accessRefCell<T>
andCell<T>
: Runtime borrow checking not thread-safeMutex<T>
: ImplementsSync
and enables multi-threaded shared access
Primitive types implement both Send
and Sync
. Types composed entirely of Send
and Sync
types automatically implement these traits.
Manual Implementation Safety
Manually implementing Send
and Sync
requires unsafe
code and careful consideration of concurrency invariants. Building new concurrent types outside the Send
/Sync
ecosystem demands deep understanding of thread safety guarantees.
For production systems, prefer established concurrent data structures from crates like crossbeam
or tokio
rather than implementing custom concurrent types.
Summary
Rust’s concurrency model combines:
- Channels: Message passing with ownership transfer
- Mutexes: Shared state with exclusive access
- Atomic types: Lock-free concurrent operations
- Send/Sync traits: Compile-time thread safety guarantees
The type system and borrow checker eliminate data races and memory safety issues at compile time, enabling fearless concurrency. Concurrent programming becomes a design decision rather than a source of runtime bugs.