Rust笔记 - std::marker::Send 和 std::marker::Sync

1,548 阅读1分钟

Rust 线程共享数据与send和sync这两个trait息息相关。

  • 一个类型实现了send trait,则可以在线程间安全的传递
  • 一个类型实现了sync trait,则可以在线程间安全的传递不变引用,可以在线程间共享数据。

如果一个类型实现了上述两个trait,则意味着在线程共享数据时能够避免 data races 和 undefined behavior。

Rust的大部分builtin types 都实现了上述两个trait。下图展示了部分数据类型。

下面看一个例子,没有实现上述两个trait的Rc<String> 在线程间共享会怎样?

fn main() {
    let s = std::rc::Rc::new("hello".to_owned());
    let s2 = s.clone();
    std::thread::spawn(move || {
        s2.push_str(" world");
    }); 
    println!("{}", s); 
}

输出的结果:

error[E0277]: `std::rc::Rc<std::string::String>` cannot be sent between threads safely
   --> b.rs:4:5
    |
4   |       std::thread::spawn(move || {
    |  _____^^^^^^^^^^^^^^^^^^_-
    | |     |
    | |     `std::rc::Rc<std::string::String>` cannot be sent between threads safely
5   | |         s2.push_str(" world");
6   | |     });
    | |_____- within this `[closure@b.rs:4:24: 6:6 s2:std::rc::Rc<std::string::String>]`
    |
    = help: within `[closure@b.rs:4:24: 6:6 s2: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@b.rs:4:24: 6:6 s2:std::rc::Rc<std::string::String>]`

error: aborting due to previous error

For more information about this error, try `rustc --explain E0277`.

由上面的错误信息可以看出,std::rc::Rc<std::string::String> 没有实现 std::mark::Send trait,无法在线程间传递值。