Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

SendSync 特征

  • 实现Send的类型可以在线程间安全的传递其所有权
  • 实现Sync的类型可以在线程间安全的共享(通过引用)
  • 若类型 T 的引用&TSend,则TSync。因为共享的前提是要能发送。

Rc传递到子线程中

use std::rc::Rc;
use std::thread;

fn main() {
  let demo = Rc::new(0);
  thread::spawn(move || {
    //          ^^^^ `Rc<i32>` cannot be sent between threads safely
    println!("{}", *demo);
  });
}

是因为Rc没有实现SendSync这两个trait

模拟实现不能移入子线程的数据

手动实现 SendSync 是不安全的。

#![feature(negative_impls)]
use std::{marker, thread};

fn main() {
    #[derive(Debug)]
    struct Demo ();

    impl Demo {
        fn new() -> Demo {
            Demo ()
        }
    }

    // 强调 Demo 不实现Sync 与 Send
    impl !marker::Sync for Demo {}
    impl !marker::Send for Demo {}

    let demo: Demo = Demo::new();
    // 下面这行会编译失败,因为 Demo 不是 Send
    thread::spawn(move || {
      //          ^^^^ 这里将会报错 Dome不能在线程之间安全发送 
        println!("move to: {:?}", demo);
    });
}

若复合类型的所有成员都是SendSync,那么该复合类型自动拥有SendSync。(自动派生) 同理。只要复合类型中有一个成员不是SendSync,那么该复合类型也就不是SendSync

裸指针也不能在线程间传递共享

use std::thread;

fn main() {
  let mut num = 5u8;  
  let mum_p = &mut num as *mut u8;
  println!("mum_p: {:p}", mum_p);
  unsafe {
    println!("mut: {}", *mum_p);
  }

  // 将裸指针移入子线程
  thread::spawn(move || {
    //          ^^^^ `*mut u8` cannot be sent between threads safely
    unsafe {
      println!("mut: {}", *mum_p);
    }
  }).join().unwrap();
}

使用Newtype 模式实现将裸指针传入子线程


use std::thread;

fn main() {
  let num = 5u8;
  let num_p = &num as *const u8;
  println!("num p = {:p}", num_p);
  unsafe {
    println!("num {}", *num_p);
  }

  // 使用newtype
  #[derive(Debug)]
  struct Wrapper(*const u8);

  impl Wrapper {
    fn value(&self) -> *const u8 {
      self.0
    }
  }

  // 为 Wrapper 实现 Send 与 Sync trait
  unsafe impl Sync for Wrapper {}
  unsafe impl Send for Wrapper {}
  // 如果注释上面两行代码将会报错

  let wrapper = Wrapper(num_p);
  thread::spawn(move || {
    let result = wrapper.value();
    unsafe { println!("in thread: {:p} = {}", result, *result); }
  }).join().unwrap();
}