写点什么

5 分钟速读之 Rust 权威指南(三十三)Send&Sync

用户头像
码生笔谈
关注
发布于: 3 小时前
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。

Send trait 允许线程间转移所有权

只有实现了 Send trait 的类型才可以安全地在线程间转移所有权,除了 Rc<T>等极少数的类型,几乎所有的 Rust 类型都实现了 Send trait。


如果我们将克隆后的 Rc<T>值的所有权转移到了另外一个线程中,那么两个线程就有可能同时更新引用计数值并进而导致计数错误。

Sync trait 允许多线程同时访问

只在线程中传递是不够的的,还需要我们在线程中能够对数据进行访问,比如前面用过的 Mutex<T>就可以在线程中访问,而 RefCell<T>就不可以:


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。


我们并不需要手动地为此种类型实现相关 trait。这两个被称作”标签 trait“,Send 与 Sync 其实并没有任何可供实现的方法。它们仅仅被用来标识并发相关的不可变性。

发布于: 3 小时前阅读数: 2
用户头像

码生笔谈

关注

欢迎关注「码生笔谈」公众号 2018.09.09 加入

前端、Rust干货分享,一起成为更好的Javascripter & Rustacean

评论

发布
暂无评论
5分钟速读之Rust权威指南(三十三)Send&Sync