5

QQA: Rust 中 Send 与 Sync 有什么区别

 3 years ago
source link: https://lotabout.me/2018/QQA-send-vs-sync-in-rust/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

QQA: Rust 中 Send 与 Sync 有什么区别

SendSync 是两个十分相近的 trait,它们是一起保证了 Rust 的线程安全,它们又有什么异同点呢?

(Quick Question and Answer 系列旨在对小问题做简短解答)

  • Send 表示数据能安全地被 move 到另一个线程
  • Sync 表示数据能在多个线程中被同时安全地访问

这里“安全”指不会发生数据的竞争 (race condition)。

Send 代表没有数据共享

数据如果被 move 到另一个线程里,它还安全吗?能正常使用吗?如果可以,则说它是 Send

反例: Rc。我们知道 Rc 中保存了一个 reference count,记录有多少变量引用了当前的数据,当 reference count 归 0 时才释放(drop)数据本身。现在如果我们把一个 Rc move 到另一个线程里,尽管是 move,Rc 的实现还是决定了不同线程里的 Rc 会指向同一个 reference count,这意味着不同的线程可能同时修改 reference count,而 Rc 内部并没有实现同步机制,因此是不安全的。

这里有一个推论:一个结构(Struct)如果不满足 Send,是不是意味着它的某个内部数据不满足Sync 呢?参考 Rc 的例子,就是内部的 reference count 不满足 Sync 。只是目前没有找到相关的证明。

Sync 代表同步

如果多个线程同时访问某个数据,会不会产生竞争?如果还是安全的,我们就能说它是 Sync

反例:RefCell。它满足 Send,但不满足 SyncRefCell 不会与本线程的其它引用共享数据,所以被 move 到其它线程是安全的。但如果有多个线程同时拥有 RefCell 的引用,并同时获取它的可变引用(mutable reference)并尝试修改它,则会产生竞争,亦即没有满足原子性。

marker trait

最后要说的是,SendSync 都属于 marker trait,marker trait 的特点是不包含任何方法,所以为某个数据结构实现 marker trait 相当于人为告诉编译器,我实现的数据结构符合你的要求(如满足 Send, Sync),编译期间就放心吧。换句话说,编译器并无法检查你的实现到底是不是满足 SendSync,只能选择相信程序员的声明,如果程序员的实现有问题,只能程序员自己背锅了。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK