You use Send, Sync, and Unpin as marker traits to tell the compiler how your custom types behave in concurrent or asynchronous contexts. Send allows a type to be transferred between threads, Sync allows a type to be shared between threads via references, and Unpin allows a type to be moved in memory after being pinned. You typically implement these automatically using #[derive] or explicitly for custom types that need specific safety guarantees.
use std::sync::Arc;
use std::thread;
// Automatically implements Send and Sync if all fields do
#[derive(Debug)]
struct MyData {
value: i32,
}
fn main() {
let data = Arc::new(MyData { value: 42 });
let handle = thread::spawn(move || {
println!("Data from thread: {}", data.value);
});
handle.join().unwrap();
}