पाठ 21 / 25

Send and Sync: Data Races at Compile Time

The type system knows what can cross threads.

Marker traits enforced by the compiler

Send marks types that can be moved to another thread; Sync marks types that can be shared between threads by reference. The compiler implements them automatically for safe types and refuses to compile code that would send a non-thread-safe type across threads. Rc (a single-threaded reference count) is neither, so it must be replaced by Arc in threaded code. This is how Rust turns many concurrency bugs into compile errors.

Sending an Rc to a thread, compile error

I compiled this with Rust 1.99.0 (cargo build); it is meant to fail. The output is trimmed to the error lines. Moving an Rc into a spawned thread fails with E0277: Rc<Vec> cannot be sent between threads safely, because Rc does not implement Send.

use std::rc::Rc;
use std::thread;

fn main() {
    let shared = Rc::new(vec![1, 2, 3]);   // Rc is not thread-safe
    let handle = thread::spawn(move || {
        println!("{:?}", shared);
    });
    handle.join().unwrap();
}

Output:

error[E0277]: `Rc<Vec<i32>>` cannot be sent between threads safely
 --> src/main.rs:6:32
  = help: within `{closure@src/main.rs:6:32: 6:39}`, the trait `Send` is not implemented for `Rc<Vec<i32>>`
 --> src/main.rs:6:32
error: could not compile `demo` (bin "demo") due to 1 previous error

Rc for one thread, Arc for many

Use Rc when everything stays on one thread (it is cheaper) and Arc when ownership crosses threads.

त्वरित जाँच: What does it mean when a type does not implement Send?

  • It cannot be printed
  • It cannot be moved to another thread
  • It cannot be cloned
  • It cannot be stored in a Vec
Answer

It cannot be moved to another thread — The compiler blocks unsafe sharing.