Sync 和 Send trait的可扩展并发

SyncSend 是内嵌在Rust语言中的 std::marker.

Send trait 允许数据在线程间转移所有权.

几乎所有的Rust类型都是Send的, 不过有一些例外, 比如 Rc<T> , 如果多个线程可能同时更新Rc的引用计数, 从而导致计数错误.

Rust展开
12345678910111213141516171819202122232425262728293031323334353637383940
use std::rc::Rc;
use std::thread;
use std::sync::{Mutex};

fn main(){
  let x = Rc::new (Mutex::new(0) );
  let mut thes = vec![];

  for _ in 0..6 {
    let x = Rc::clone(&x);
    let th = thread::spawn(move ||{
      let mut y = x.lock().unwrap();
      *y = *y + 1;
    });
    thes.push(th);
  }

  for th in thes {
      th.join().unwrap();
  }

  println!("{}", x.lock().unwrap());
}
/**********************output*************************/
error[E0277]: `Rc<Mutex<i32>>` cannot be sent between threads safely
   --> src/main.rs:11:14
    |
11  |       let th = thread::spawn(move ||{
    |  ______________^^^^^^^^^^^^^_-
    | |              |
    | |              `Rc<Mutex<i32>>` cannot be sent between threads safely
12  | |       let mut y = x.lock().unwrap();
13  | |       *y = *y + 1;
14  | |     });
    | |_____- within this `[closure@src/main.rs:11:28: 14:6]`
    |
    = help: within `[closure@src/main.rs:11:28: 14:6]`, the trait `Send` is not implemented for `Rc<Mutex<i32>>`
    = note: required because it appears within the type `[closure@src/main.rs:11:28: 14:6]`
note: required by a bound in `spawn`

通过Send Rust 可以保证不会意外的将未实现Sendtrait 的数据在线程间转移.

任何完全由Send标记的的类型组成的数据,也会被标记为Send. 除了 裸指针(raw pointer)外, 所有的基本类型都是可Send

Sync允许多线程间的安全访问, 实现了Sync的类型可以在多个线程中拥有其值的引用.

对任意类型T ,如果 &T 实现了Send , 则T是Sync, 也即意味着他的引用可以安全的发送到多个线程中.

Send类似, 基本类型是Sync的,完全有实现了Sync的类型组成的类型也是 Sync的.

RefCellCell 都不是Sync的, 因为运行时的借用检查不是线程安全的.

通常并不需要手动实现SendSync , 他们是标记trait, 甚至都没有需要实现的方法. 他们只是用来标注并发相关的检查

Rust展开
1234567891011121314151617181920
#[derive(Send, Sync)]
struct A{}

/***************output**************/
error: cannot find derive macro `Send` in this scope
 --> src/lib.rs:1:10
  |
1 | #[derive(Send)]
  |          ^^^^
  |
note: unsafe traits like `Send` should be implemented explicitly


error: cannot find derive macro `Sync` in this scope
 --> src/lib.rs:1:16
  |
1 | #[derive(Send, Sync)]
  |                ^^^^
  |
note: unsafe traits like `Sync` should be implemented explicitly

- roadup -