Sync
在结束本章之前,让我们谈谈Rust标准库中的另一个关键特性:Sync
。
Sync
是一个自动特质,就像Send
一样。它被所有类型自动实现,这些类型能够在线程间安全地共享。
换句话说:T: Sync
意味着&T
是Send
。
Sync
并不意味着Send
需要注意的是,Sync
并不意味着Send
。例如:MutexGuard
不是Send
,但是它是Sync
。
它不是Send
,因为锁必须在获取它的同一个线程上释放,因此我们不希望MutexGuard
在不同的线程上被丢弃。但它又是Sync
,因为将&MutexGuard
传递给另一个线程并不会影响锁在哪里释放。
Send
并不意味着Sync
反之亦然:Send
并不意味着Sync
。例如:RefCell<T>
是Send
(如果T
是Send
的话),但它不是Sync
。
RefCell<T>
执行运行时借用检查,但它使用的用于跟踪借用的计数器不是线程安全的。因此,多个线程持有&RefCell
会导致数据竞争,可能会有多个线程获得对同一数据的可变引用。因此RefCell
不是Sync
。而Send
是可以的,因为我们向另一个线程发送RefCell
时,并没有留下对其包含数据的任何引用,因此没有并发修改访问的风险。