结论:Send 表示类型可以安全地把所有权转移到另一个线程;Sync 表示类型可以安全地被多个线程通过共享引用同时访问(等价于 &T: Send)。二者是编译器按字段递归自动实现的 marker trait,是 Rust"无畏并发"的根基。
展开:绝大多数类型都是 Send + Sync;例外揭示设计意图:Rc<T> 既非 Send 也非 Sync(引用计数非原子操作);Cell/RefCell 是 Send 但非 Sync(无同步的运行时可变);Mutex<T> 只要 T: Send 就 Send + Sync(锁提供了同步);原始指针不是 Send/Sync,防止 unsafe 代码无意中跨线程。unsafe 代码可以 unsafe impl Send/Sync,但实现者须自行担保线程安全——Mutex、Arc 正是这样做的。易错点:Send 不等于"可共享",共享需要 Sync;Rc 不能 Send 的原因是两个线程同时克隆/丢弃会造成计数竞态,可能提前释放或泄漏。
fn assert_send_sync<T: Send + Sync>() {}
assert_send_sync::<i32>();
assert_send_sync::<std::sync::Mutex<String>>();
// assert_send_sync::<std::rc::Rc<i32>>(); // 编译错误