天天看点

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 {}