前面幾節事後,併發的基本使用就聊完了,最後還剩下一點,前面咱們在建立線程後,容許將數據的全部權轉移到線程中(好比: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