Rust中Send和Sync有什么区别

2023-04-25,,

Rust中Send和Sync有什么区别,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。

定义

  • Send: 变量可以安全的发送给另一个线程,

  • Sync:可以在多个线程之前共享,(当且仅当&T实现了Send时,T实现了Send)

典型的例子是

  • Rc即不是Send也不是Sync

  • Cell、RefCell是Send,不是Sync。

Send限制变量的move。Rust中所有的变量都是可以move的,但是要实现跨越线程的move,变量必需实现Send。

如下面的例子

fn main() {
    let msg = "message".to_string();
    std::thread::spawn(move || {
        println!("msg={:?}", msg);
    }).join();

    let msg = std::rc::Rc::new("message".to_string());
    std::thread::spawn(move || {
        println!("msg={:?}", msg);
    }).join();
}

编译时会报错

error[E0277]: `std::rc::Rc<std::string::String>` cannot be sent between threads safely
   --> src/main.rs:8:5
    |
8   |       std::thread::spawn(move || {
    |  _____^^^^^^^^^^^^^^^^^^_-
    | |     |
    | |     `std::rc::Rc<std::string::String>` cannot be sent between threads safely
9   | |         println!("msg={:?}", msg);
10  | |     }).join();
    | |_____- within this `[closure@src/main.rs:8:24: 10:6 msg:std::rc::Rc<std::string::String>]`
    |
    = help: within `[closure@src/main.rs:8:24: 10:6 msg:std::rc::Rc<std::string::String>]`, the trait `std::marker::Send` is not implemented for `std::rc::Rc<std::string::String>`
    = note: required because it appears within the type `[closure@src/main.rs:8:24: 10:6 msg:std::rc::Rc<std::string::String>]`

error: aborting due to previous error

String类型实现了Send,所以可以move到另一个线程。Rc这种可以通过Rc::clone()复制多个Rc,Rc的引用计数的增减非原子操作,多线程环境下会出错,所以Rc没有实现Send。

而Sync本质上是要保证&T是Send的。Rust中变量在同一时间可以有多个不可变引用,对于String,Vec这些类型,不同的线程可以共享不可变引用,相当于多个线程共同读。

Rust中无法实现Sync的主要有两种

  • Rc这种引用计数的类型

  • Cell和RefCell 这类提供了内部可变性的类型。

Cell和RefCell提供内部可变性,即使拥有的是不可变饮用,也可以修改变量内部的值,所以这两个无法实现Send。如果需要跨线程的内部可变性,可以使用Mutex或者Atomic类型。

关于Rust中Send和Sync有什么区别问题的解答就分享到这里了,希望以上内容可以对大家有一定的帮助,如果你还有很多疑惑没有解开,可以关注本站行业资讯频道了解更多相关知识。

《Rust中Send和Sync有什么区别.doc》

下载本文的Word格式文档,以方便收藏与打印。