5分鐘速讀之Rust權威指南(三十三)Send&Sync

Send trait和Sync trait

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

只有實現了Send trait的類型才能夠安全地在線程間轉移全部權,除了Rc<T>等極少數的類型,幾乎全部的Rust類型都實現了Send trait。多線程

若是咱們將克隆後的Rc<T>值的全部權轉移到了另一個線程中,那麼兩個線程就有可能同時更新引用計數值並進而致使計數錯誤。併發

Sync trait容許多線程同時訪問

只在線程中傳遞是不夠的的,還須要咱們在線程中可以對數據進行訪問,好比前面用過的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的類型組成時,它就會自動實現Send與Sync。code

咱們並不須要手動地爲此種類型實現相關trait。這兩個被稱做」標籤trait「,Send與Sync其實並無任何可供實現的方法。它們僅僅被用來標識併發相關的不可變性。orm

相關文章
相關標籤/搜索