In this lesson, you will learn how Rust uses the Send and Sync marker traits to enforce thread safety at the type level.
When working with concurrent data structures—like those using Arc<Mutex<T>> or Atomic types—the Rust compiler must guarantee that data races cannot occur. It does this by checking whether your types are safe to pass between threads or access from multiple threads simultaneously.
The Role of Marker Traits
These checks are handled by two fundamental marker traits defined in the standard library:
Send: A type isSendif it is safe to transfer ownership of it to another thread. Most Rust types areSend, but types that hold non-thread-safe resources (likeRc<T>, which uses a non-atomic reference counter) are not.Sync: A type isSyncif it is safe to share between threads via shared references (&T). A typeTisSyncif and only if&TisSend.
Enforcing Safety at Compile Time
Consider an Rc<T>. Because Rc updates its reference count without atomic operations, it is not thread-safe. If you try to move an Rc into a new thread, the compiler checks the Send trait. Since Rc explicitly opts out of Send, the compiler will throw an error, preventing a potential data race on the reference count.
When you use Arc<T>, you are using a version of reference counting that satisfies the Send and Sync requirements because it uses atomic operations for its counter.
use std::sync::Arc;
use std::rc::Rc;
use std::thread;
fn main() {
let shared = Arc::new(5); // Arc is Send + Sync
thread::spawn(move || {
println!("{:?}", shared);
});
// let local = Rc::new(5);
// thread::spawn(move || { println!("{:?}", local); });
// ^ Error: Rc<i32> cannot be sent between threads safely
}
The beauty of this system is that it is entirely type-driven. You don't need to manually label your structs; the compiler automatically derives Send and Sync based on the fields of your type. If all fields are Send or Sync, your struct is too. If you include an unsafe component, you can manually implement these traits only after verifying the logic is sound.
Key Takeaway: The Send and Sync marker traits are the compiler's primary mechanism for ensuring that concurrent data access remains memory-safe by blocking non-thread-safe types from crossing thread boundaries.