Quick Contact

✉
fahimkhan20148@gmail.com
📱
+971 507 286 133
Back to Notes
August 18, 2026
rustconcurrencythread-safety

Thread Safety in Rust: Send and Sync

Thread safety markers determine how types can cross thread boundaries:

  • Send: A type T is Send if its ownership can be transferred to another thread.
  • Sync: A type T is Sync if its shared reference is of type Send (i.e., T is Sync if &T is Send).

All primitive types are Send and Sync. Types are automatically Send and Sync if all of their fields are Send and Sync.

Send

A type T is Send if its ownership can be transferred to another thread. e.g., Arc<T> is Send, but Rc<T> is not.

Sync

A type T is Sync if its shared reference is of type Send (i.e., T is Sync if &T is Send). e.g., i32 is Sync, but Cell<i32> is not Sync.

All primitive types are Send and Sync.

Auto Traits

Auto traits are traits which are implemented for a type if all of its fields implement them.

i.e.

struct User {
	id: i32,
}

Here, User is both Send and Sync because id is Send and Sync.

To opt out, you can add a property that's not Send or Sync, like a Cell:

use std::cell::Cell;
use std::marker::PhantomData;

struct User {
	id: i32,
	__not_sync: PhantomData<Cell<()>>,
}

Now User is not Sync or Send.

Raw pointers like *const T and *mut T are neither Send nor Sync as the compiler cannot guarantee thread safety for them.

struct Org {
	user: *mut usize,
}

unsafe impl Send for Org {}
unsafe impl Sync for Org {}

We need to use unsafe because the compiler can't guarantee that the value the user references is Send or Sync.