Rust prevents data races at compile time through its Ownership system, specifically the Borrow Checker and the Send and Sync traits. The compiler enforces rules that ensure data is either owned by a single thread or shared via immutable references, rejecting code that allows simultaneous mutable access from multiple threads.
use std::thread;
fn main() {
let data = String::from("hello");
// This code fails to compile because `data` is moved to the thread
// and cannot be accessed mutably in the main thread simultaneously.
let handle = thread::spawn(|| {
println!("{}", data);
});
handle.join().unwrap();
}