前面几节事后,并发的基本使用就聊完了,最后还剩下一点,前面咱们在建立线程后,容许将数据的全部权转移到线程中(好比:i32,String,Vec<T>, Arc<T>等),可是并不是全部数据均可以转移,好比当咱们前面尝试将Rc<T>全部权转移到线程中时就会报错:安全
use std::rc::Rc;
use std::thread;
let a = Rc::new(1);
let a2 = a.clone();
thread::spawn(|| {
a2; // 报错,Rc<i32>不能在线程之间安全地发送
});
复制代码
实际上在于Rc<T>没有Send trait,而rust大部分类型都实现了这个trait。markdown
只有实现了Send trait的类型才能够安全地在线程间转移全部权,除了Rc<T>等极少数的类型,几乎全部的Rust类型都实现了Send trait。多线程
若是咱们将克隆后的Rc<T>值的全部权转移到了另一个线程中,那么两个线程就有可能同时更新引用计数值并进而致使计数错误。并发
只在线程中传递是不够的的,还须要咱们在线程中可以对数据进行访问,好比前面用过的Mutex<T>就能够在线程中访问,而RefCell<T>就不能够:spa
use std::cell::RefCell;
use std::thread;
let a = RefCell::new(1);
thread::spawn(|| {
a.borrow_mut(); // 报错,RefCell<i32>不能在线程之间安全共享
});
复制代码
只有实现了Sync trait的类型才能够安全地被多个线程引用,类型Mutex<T>是Sync的,能够被多个线程共享访问,类型RefCell<T>不知足Sync约束,实现的运行时借用检查并无提供有关线程安全的保证。线程
当某个类型彻底由实现了Send与Sync的类型组成时,它就会自动实现Send与Sync。code
咱们并不须要手动地为此种类型实现相关trait。这两个被称做”标签trait“,Send与Sync其实并无任何可供实现的方法。它们仅仅被用来标识并发相关的不可变性。orm