天天看點

024 Rust死靈書之Send和Sync

介紹

本系列錄制的視訊主要放在B站上​​Rust死靈書學習視訊​​

Rust 死靈書相關的源碼資料在https://github.com/anonymousGiga/Rustonomicon-Source

Send和Sync

當同一塊記憶體有多個别名,同時還可以改變記憶體的值的時候,它們就不是線程安全的。

Rust中根據Send和Sync trait擷取相關的資訊:

1、如果一個類型可以安全地傳遞給另一個線程,那麼這個類型是實作了Send這個trait了的;
2、如果一個類型可以安全地被多個線程共享,那麼這個類型就是Sync的。      

Send和Sync是Rust并發機制的基礎,但是它們是非安全的trait。Send和Sync是标志trait(即沒有任何關聯方法),類型要實作它們其實就是滿足它們需要的内部特征。不正确的實作Send和Sync會導緻未定義行為。

Send和Sync是自動推到的trait,規則:

1、如果一個類型完全由Send或者Sync組成,那麼這個類型本身也是Send或者Sync的;
2、幾乎所有的基本類型都是Send和Sync的。      

例外情況:

1、裸指針不是Send的,也不是Sync的;
2、UnsafeCell不是Sync的(Cell和RefCell也不是);
3、Rc不是Send或Sync的(引用計數是共享且非同步的)。      

Rc和UnsafeCell是典型的非線程安全的,因為它們允許非同步地共享可變狀态。

不能自動推導的類型也可以很容易的實作Send和Sync:

struct MyBox(*mut u8);

unsafe impl Send for MyBox {}
unsafe impl Sync for MyBox {}      
#![feature(negative_impls)]

// I have some magic semantics for some synchronization primitive!
struct SpecialThreadToken(u8);

impl !Send for SpecialThreadToken {}
impl !Sync for SpecialThreadToken {}