Skip to content

基于 Send 和 Sync 的线程安全

一、Rc 和 Arc 源码对比

rust
// Rc源码片段
impl<T: ?Sized> !marker::Send for Rc<T> {} // 此处Send被移除了
impl<T: ?Sized> !marker::Sync for Rc<T> {} // 此处Sync被移除了

// Arc源码片段
unsafe impl<T: ?Sized + Sync + Send> Send for Arc<T> {}
unsafe impl<T: ?Sized + Sync + Send> Sync for Arc<T> {}
// Rc源码片段
impl<T: ?Sized> !marker::Send for Rc<T> {} // 此处Send被移除了
impl<T: ?Sized> !marker::Sync for Rc<T> {} // 此处Sync被移除了

// Arc源码片段
unsafe impl<T: ?Sized + Sync + Send> Send for Arc<T> {}
unsafe impl<T: ?Sized + Sync + Send> Sync for Arc<T> {}

!代表移除特征的相应实现,上面代码中Rc<T>的Send和Sync特征被特地移除了实现,而Arc<T>则相反,实现了Sync + Send,再结合之前的编译器报错,大概可以明白了:Send和Sync是在线程间安全使用一个值的关键。

二、Send 和 Sync

SendSync是 Rust 安全并发的重中之重,但是实际上它们只是标记特征(marker trait,该特征未定义任何行为,因此非常适合用于标记), 来看看它们的作用:

  • 实现Send的类型可以在线程间安全的传递其所有权
  • 实现Sync的类型可以在线程间安全的共享(通过引用)