最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

Rust Send、Sync trait理解

网站源码admin8浏览0评论

Rust Send、Sync trait理解

Rust的异步并发编程中,大量的接口参数、返回值要求类型为Send、Sync,那这2个trait到底是什么意思,有什么区别,为什么在异步编程中需要他们,以及类型是如何实现这些trait的;本文会从上面几个问题入手带你深入了解这2个trait.

Send、Sync 语义

Sync:1)行为上:允许一个对象在多个线程中被同时使用;2)原理上:将一个实现了Sync类型的不可变引用安全的传递给另一个线程,即只有实现了Sync Trait的类型才可以安全地被多个线程引用

  • 但对于可变对象如果想要是Sync的,就需要用同步原语进行多线程同步(如: Mutex, RwMutex)将这些非Sync对象变为Sync对象,另一种机制就是使用原子类型进行处理。
  • 对于任何类型T,如果&T(也就是T的引用)满足约束Send,那么T类型就是实现了Sync的类型,因为它的引用可以安全的发送给其它线程,允许多个线程在同一时间通过引用安全的使用同一对象。

Send: 1) 行为上:允许一个对象在多个线程中在不同时间被使用, 2) 原理上:允许对象在线程间转移所有权,只有实现了Send trait的类型才可以在线程间转移所有权

  • 如:线程A创建、并使用一个对象一会,然后再将这个对象发送给线程B,这时线程B就可以使用这个对象而线程 A则无法使用。Rust的ownership语义保证了这个对象不会在2个线程中被同时使用、从而保证线程的Send对象的线程安全。

区别

从上面的解释可以看到,2者重要的区别是:行为上:多线程中同一个对象的使用方式,Sync属性的对象可以在多线程中被同时使用,而Send属性的对象同一时间只能有一个线程使用。原理上:一个是按值传递涉及所有权的转移,另一个是按引用传递.

Rust中大多数类型既实现了Send也实现了Sync,甚至不必为自定义的结构体/枚举手动实现这些trait,Rust会自动帮你实现;如果结构体或枚举的所有字段都是Send那它也是Send,同理Sync。

但Rust中有些类型刻意设计为Send但非Sync的,如:mpsc::Receiver类型,保证了mpsc通道的接收端一次只能被一个线程使用。

少数既不是Send也 不是Sync的类型大多数使用了非线程安全的内部可变性,如引用计数器指针:std::rc::Rc<T>;

  • 如果Rc<String>是Sync的,那么在线程间通过共享引用共享单个Rc时就会出发数据竞争,如:2个线程同时增加共享引用计数会导致引用技术结果变得不准确。

在异步编程中对于跨线程边界使用的函数,Send、Sync会作为函数类型签名中的约束。当spawn一个线程时传入的闭包必须实现了Send trait,意味着它包含的所有值都必须是Send;同样如果通过通道将值发送到另一个线程,该值也必须是Send.

参考

Rust 程序设计(第2版)

Rust 权威指南

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论